React路由

284 阅读2分钟

React路由

"react-router-dom": "^6.2.2"

  1. 安装react-router-dom

    • 在React项目里安装 react-router-dom

      npm install react-router-dom@6
      
    • 引入标签

      import { BrowserRouter, Routes, Route } from "react-router-dom";
      
    • 基本用法

      src/index.js
      
      import React from 'react';
      import ReactDOM from 'react-dom';
      import {
        BrowserRouter,
        Routes,
        Route,
      } from "react-router-dom";
      import App from './App';
      import Expenses from "./routes/expenses";
      import Invoices from "./routes/invoices";
      
      ReactDOM.render(
          <BrowserRouter>
            <Routes>
              <Route path="/" element={<App />} />
              <Route path="expenses" element={<Expenses />} />
              <Route path="invoices" element={<Invoices />} />
            </Routes>
          </BrowserRouter>,
          document.getElementById('root')
      );
      
  2. 使用嵌套路由

    • 需要引入Outlet

      import { Outlet, Link } from "react-router-dom";
      
    • 代码

      src/App.js
      
      import { Outlet, Link } from "react-router-dom";
      
      function App() {
        return (
          <div className="App">
            <header className="App-header">
                <nav>
                  <Link to="/invoices">Invoices</Link> |{" "}
                  <Link to="/expenses">Expenses</Link>
                </nav>
                <Outlet />
            </header>
          </div>
        );
      }
      
      export default App;
      
    • 将expenses和invoices作为根路由的子级,作为子级它们共享App组件里的样式

      src/index.js
      
      import React from 'react';
      import ReactDOM from 'react-dom';
      import {
        BrowserRouter,
        Routes,
        Route,
      } from "react-router-dom";
      import App from './App';
      import Expenses from "./routes/expenses";
      import Invoices from "./routes/invoices";
      
      ReactDOM.render(
          <BrowserRouter>
            <Routes>
              <Route path="/" element={<App />}>
                <Route path="expenses" element={<Expenses />} />
                <Route path="invoices" element={<Invoices />} />
              </Route>
            </Routes>
          </BrowserRouter>,
          document.getElementById('root')
      );
      
  3. 添加不匹配路由

    • 当没有路由匹配时,便会匹配*

      <Routes>
        <Route path="/" element={<App />}>
          <Route path="expenses" element={<Expenses />} />
          <Route path="invoices" element={<Invoices />} />
          <Route
            path="*"
            element={
              <main style={{ padding: "1rem" }}>
                <p>没有匹配的路由!</p>
              </main>
            }
          />
        </Route>
      </Routes>
      
  4. 读取URL参数

    • 我们要读取/invoices/2005中的2005,先在invoices下创建一个子路由,值命名为invoiceId。注意:Invoices 和 Invoice 是两个不同的组件

      <Routes>
        <Route path="/" element={<App />}>
          <Route path="expenses" element={<Expenses />} />
          <Route path="invoices" element={<Invoices />}>
            <Route path=":invoiceId" element={<Invoice />} />
          </Route>
          <Route
            path="*"
            element={
              <main style={{ padding: "1rem" }}>
                <p>没有匹配的路由!</p>
              </main>
            }
          />
        </Route>
      </Routes>
      
    • 在 Invoices 组件中增加一个 Outlet 用来显示 Invoice

      import { Outlet, Link } from "react-router-dom";
      
      export default function Invoices() {
          return (
            <main style={{ padding: "1rem 0", display: "flex" }} >
              <div style={{ marginRight: "100px", display: "flex", flexDirection: "column"}}>
                  <Link to="/invoices/2005">2005</Link>
                  <Link to="/invoices/2006">2006</Link>
                  <Link to="/invoices/2007">2007</Link>
                  <Link to="/invoices/2008">2008</Link>
                  <Link to="/invoices/2009">2009</Link>
                  <Link to="/invoices/2010">2010</Link>
              </div>
              <div>
                  <Outlet />
              </div>
            </main>
          );
      }
      
    • 在 Invoice 中引入useParams用来读取值

      import { useParams } from "react-router-dom";
      
      export default function Invoices() {
          let params = useParams();
          let invoiceId = parseInt(params.invoiceId, 10);
          return (
            <main>
              <div>invoiceId: {invoiceId}</div>
            </main>
          );
      }
      
  5. 索引路由

    • 当父路由匹配,但子路由不匹配时,便会匹配索引路由。例如:我们访问 /invoices,但因为没有子路由匹配,所以不展示页面,这时如果有索引路由便会展示索引路由。索引路由是父路由的默认子路由。

      <BrowserRouter>
        <Routes>
          <Route path="/" element={<App />}>
            <Route path="expenses" element={<Expenses />} />
            <Route path="invoices" element={<Invoices />}>
              <Route
                index
                element={
                  <main style={{ padding: "1rem" }}>
                    <p>请选择一张发票</p>
                  </main>
                }
              />
              <Route path=":invoiceId" element={<Invoice />} />
            </Route>
          </Route>
          <Route
            path="*"
            element={
              <main style={{ padding: "1rem" }}>
                <p>没有匹配的路由!</p>
              </main>
            }>
          </Route>
        </Routes>
      </BrowserRouter>
      
  6. NavLink

    • 用来高亮当前路由的链接

      import { NavLink } from "react-router-dom";
      
      // 如果当前路径是 /invoices/2005,那么它的className就会变成"red"
      <NavLink className={({ isActive }) => isActive ? "red" : "blue" to="/invoices/2005"}>2005</NavLink>
      
      <NavLink
        style={({ isActive }) => ({
          display: "block",
          margin: "1rem 0",
          color: isActive ? "red" : "",
        })}
        to="/invoices/2005"}
      >
        2005
      </NavLink>
      
  7. 搜索参数

    • 引入 useSearchParams

      import { useSearchParams } from "react-router-dom";
      
    • 通过 searchParams.get() 获取参数。通过 setSearchParams({}); 获取参数

      let [searchParams, setSearchParams] = useSearchParams();
      
      // 当前URL /invoices/2005?filter=test
      searchParams.get("filter") // test
      
      // 设置URL为 /invoices/2005?filter=200
      setSearchParams({ filter: 200 });