git clone https://github.com/ReactTraining/react-router.git

packages

image.png

react-router 使用Demo

  1. // #: npx create-react-app demo-app
  2. // #: cd demo-app
  3. // #: npm install react-router-dom
  4. // 例子 1
  5. import React from "react";
  6. import {
  7. BrowserRouter as Router,
  8. Switch,
  9. Route,
  10. Link
  11. } from "react-router-dom";
  12. export default function App() {
  13. return (
  14. <Router>
  15. <div>
  16. <nav>
  17. <ul>
  18. <li>
  19. <Link to="/">Home</Link>
  20. </li>
  21. <li>
  22. <Link to="/about">About</Link>
  23. </li>
  24. <li>
  25. <Link to="/users">Users</Link>
  26. </li>
  27. </ul>
  28. </nav>
  29. {/* A <Switch> looks through its children <Route>s and
  30. renders the first one that matches the current URL. */}
  31. <Switch>
  32. <Route path="/about">
  33. <About />
  34. </Route>
  35. <Route path="/users">
  36. <Users />
  37. </Route>
  38. <Route path="/">
  39. <Home />
  40. </Route>
  41. </Switch>
  42. </div>
  43. </Router>
  44. );
  45. }
  46. function Home() {
  47. return <h2>Home</h2>;
  48. }
  49. function About() {
  50. return <h2>About</h2>;
  51. }
  52. function Users() {
  53. return <h2>Users</h2>;
  54. }
  55. // 例子 2
  56. import {
  57. BrowserRouter as Router,
  58. Switch,
  59. Route,
  60. Link,
  61. useRouteMatch,
  62. useParams
  63. } from "react-router-dom";
  64. export default function App() {
  65. return (
  66. <Router>
  67. <div>
  68. <ul>
  69. <li>
  70. <Link to="/">Home</Link>
  71. </li>
  72. <li>
  73. <Link to="/about">About</Link>
  74. </li>
  75. <li>
  76. <Link to="/topics">Topics</Link>
  77. </li>
  78. </ul>
  79. <Switch>
  80. <Route path="/about">
  81. <About />
  82. </Route>
  83. <Route path="/topics">
  84. <Topics />
  85. </Route>
  86. <Route path="/">
  87. <Home />
  88. </Route>
  89. </Switch>
  90. </div>
  91. </Router>
  92. );
  93. }
  94. function Home() {
  95. return <h2>Home</h2>;
  96. }
  97. function About() {
  98. return <h2>About</h2>;
  99. }
  100. function Topics() {
  101. let match = useRouteMatch();
  102. return (
  103. <div>
  104. <h2>Topics</h2>
  105. <ul>
  106. <li>
  107. <Link to={`${match.url}/components`}>Components</Link>
  108. </li>
  109. <li>
  110. <Link to={`${match.url}/props-v-state`}>
  111. Props v. State
  112. </Link>
  113. </li>
  114. </ul>
  115. {/* The Topics page has its own <Switch> with more routes
  116. that build on the /topics URL path. You can think of the
  117. 2nd <Route> here as an "index" page for all topics, or
  118. the page that is shown when no topic is selected */}
  119. <Switch>
  120. <Route path={`${match.path}/:topicId`}>
  121. <Topic />
  122. </Route>
  123. <Route path={match.path}>
  124. <h3>Please select a topic.</h3>
  125. </Route>
  126. </Switch>
  127. </div>
  128. );
  129. }
  130. function Topic() {
  131. let { topicId } = useParams();
  132. return <h3>Requested topic ID: {topicId}</h3>;
  133. }

react-router-dom 阅读入门

打开packages目录,在继续打开react-router-dom目录
里面有一个 rollup.config.js 此文件是用来build用的

  1. input: "modules/index.js",
  2. output: {
  3. file: `cjs/${pkg.name}.js`,
  4. sourcemap: true,
  5. format: "cjs",
  6. esModule: false
  7. },

打开index.js查看,我们发现目录中是没有cjs目录的,cjs目录由modules/index.js生成

  1. "use strict";
  2. if (process.env.NODE_ENV === "production") {
  3. module.exports = require("./cjs/react-router-dom.min.js");
  4. } else {
  5. module.exports = require("./cjs/react-router-dom.js");
  6. }

modules/index.js

  1. export {
  2. MemoryRouter,
  3. Prompt,
  4. Redirect,
  5. Route,
  6. Router,
  7. StaticRouter,
  8. Switch,
  9. generatePath,
  10. matchPath,
  11. withRouter,
  12. useHistory,
  13. useLocation,
  14. useParams,
  15. useRouteMatch
  16. } from "react-router";
  17. export { default as BrowserRouter } from "./BrowserRouter.js";
  18. export { default as HashRouter } from "./HashRouter.js";
  19. export { default as Link } from "./Link.js";
  20. export { default as NavLink } from "./NavLink.js";

modules/HashRouter.js

  1. import React from "react";
  2. import { Router } from "react-router";
  3. import { createHashHistory as createHistory } from "history";
  4. import PropTypes from "prop-types";
  5. import warning from "tiny-warning";
  6. /**
  7. * The public API for a <Router> that uses window.location.hash.
  8. */
  9. class HashRouter extends React.Component {
  10. history = createHistory(this.props);
  11. render() {
  12. return <Router history={this.history} children={this.props.children} />;
  13. }
  14. }
  15. if (__DEV__) {
  16. HashRouter.propTypes = {
  17. basename: PropTypes.string,
  18. children: PropTypes.node,
  19. getUserConfirmation: PropTypes.func,
  20. hashType: PropTypes.oneOf(["hashbang", "noslash", "slash"])
  21. };
  22. HashRouter.prototype.componentDidMount = function() {
  23. warning(
  24. !this.props.history,
  25. "<HashRouter> ignores the history prop. To use a custom history, " +
  26. "use `import { Router }` instead of `import { HashRouter as Router }`."
  27. );
  28. };
  29. }
  30. export default HashRouter;

modules/BrowserRouter.js

  1. import React from "react";
  2. import { Router } from "react-router";
  3. import { createBrowserHistory as createHistory } from "history";
  4. import PropTypes from "prop-types";
  5. import warning from "tiny-warning";
  6. /**
  7. * The public API for a <Router> that uses HTML5 history.
  8. */
  9. class BrowserRouter extends React.Component {
  10. history = createHistory(this.props);
  11. render() {
  12. return <Router history={this.history} children={this.props.children} />;
  13. }
  14. }
  15. if (__DEV__) {
  16. BrowserRouter.propTypes = {
  17. basename: PropTypes.string,
  18. children: PropTypes.node,
  19. forceRefresh: PropTypes.bool,
  20. getUserConfirmation: PropTypes.func,
  21. keyLength: PropTypes.number
  22. };
  23. BrowserRouter.prototype.componentDidMount = function() {
  24. warning(
  25. !this.props.history,
  26. "<BrowserRouter> ignores the history prop. To use a custom history, " +
  27. "use `import { Router }` instead of `import { BrowserRouter as Router }`."
  28. );
  29. };
  30. }
  31. export default BrowserRouter;

HashRouter 与 BrowserRouter的区别

HashRouter 是基于Hash的 也就是浏览器地址栏中的#xxx 锚定位,锚链接
BrowserRouter [ˈbraʊzə(r)] 浏览器,是基于H5 history 这个我们放到后面章节仔细分析