react-router官網demo解析3-巢狀路由

2021-04-08 18:00:52

原始碼:
example.js

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useParams,
  useRouteMatch
} from "react-router-dom";

export default function NestingExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/topics">Topics</Link>
          </li>
        </ul>

        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/topics">
            <Topics />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function Topics() {
  let { path, url } = useRouteMatch();

  return (
    <div>
      <h2>Topics</h2>
      <ul>
        <li>
          <Link to={`${url}/rendering`}>Rendering with React</Link>
        </li>
        <li>
          <Link to={`${url}/components`}>Components</Link>
        </li>
        <li>
          <Link to={`${url}/props-v-state`}>Props v. State</Link>
        </li>
      </ul>

      <Switch>
        <Route exact path={path}>
          <h3>Please select a topic.</h3>
        </Route>
        <Route path={`${path}/:topicId`}>
          <Topic />
        </Route>
      </Switch>
    </div>
  );
}

function Topic() {
  let { topicId } = useParams();

  return (
    <div>
      <h3>{topicId}</h3>
    </div>
  );
}

效果圖:
image.png
————————————————————分割線———————————————————
image.png

相關知識:
巢狀路由:實現巢狀路由需要在一個<Route></Route>包裹的子元件中再使用<Route></Route>進行包裹內容即可。例如上面的 <Topics />元件。

useRouteMatch( ): 不帶引數的時候,返回當前元件路由匹配到的路徑內容。
如果帶引數,則相當於<Route></Route>的功能,可以進行路由匹配的判斷,並且不需要渲染<Route>元件。

解析:
頁面由兩個部分組成,ul包裹的兩個link標籤Home和Topics以及<Switch>包裹的路由元件,其中只有一個路由會被匹配並渲染。
前兩個圖,是頁面的主要兩個元件,<Home />和 <Topics />根據路由為/ 或者 /topics進行對應的渲染。
對於<Topics />元件,裡面又包括兩個部分,<h2>Topics</h2>,ul包裹的三個link和
<Switch>包裹的路由元件。這裡面的路徑必須和之前的路徑進行拼接,
例如

<Link to={`${url}/rendering`}>Rendering with React</Link>
<Route path={`${path}/:topicId`}>

這樣才可以對之前對內容進行保留。例如:
路徑為:/topics/components 則會分別匹配到<Route path="/topics"> 渲染出<Topics />並且匹配到<Route path={${path}/:topicId}>渲染出<Topic />。