八、React-Router


组件

  • BrowserRouter:整个前端路由以 history 模式开始,包裹根组件
  • HashRouter:整个前端路由以 hash 模式开始,包裹根组件
  • Routes:类似于 v5 版本的 Switch,主要是提供一个上下文环境
  • Route:在 Route 组件中书写你对应的路由,以及路由所对应的组件
    • path:匹配的路由
    • element:匹配上该路由时,要渲染的组件
  • Navigate:导航组件,类似于 useNavigate 的返回值函数,只不过这是一个组件
  • NavLink:类似于 Link,最终和 Link 一样,会被渲染为 a 标签,注意它和 Link 的区别,实际上就是当前链接,会有一个名为 active 的激活样式,所以一般用于做顶部或者左侧导航栏的跳转

Hooks

  • useLocation:获取到 location 对象,获取到 location 对象后,我们可以获取 state 属性,这往往是其他路由跳转过来的时候,会在 state 里面传递额外的数据
  • useNavigate:调用之后会返回一个函数,通过该函数可以做跳转。
  • useParams:获取动态参数

补充内容

useRoutes

使用示例如下:

function Router(props) {
  return useRoutes([
    {
      path: "/home",
      element: <Home />,
    },
    {
      path: "/about",
      element: <About />,
    },
    {
      path: "/add",
      element: <AddOrEdit />,
    },
    {
      path: "/detail/:id",
      element: <Detail />,
    },
    {
      path: "/edit/:id",
      element: <AddOrEdit />,
    },
    {
      path: "/",
      element: <Navigate replace to="/home" />
    }
  ]);
}

export default Router;

嵌套路由

直接在 useRoutes 进行 chilren 属性的配置即可,类似于 vue-router,children 对应的是一个数组,数组里面是一个一个路由对象

{
  path: "/about",
    element: <About />,
    children : [
    {
      path : "email",
      element : <Email/>
    },
    {
      path : "tel",
      element : <Tel/>
    },
    {
      path : "",
      element: <Navigate replace to="email" />
    }
  ]
},

之后,使用 Outlet 组件,该组件表示匹配上的子路由组件渲染的位置。

代码示例:

import React from "react";
import { useRoutes, Navigate } from "react-router-dom";

import Home from "../components/Home";
import About from "../components/About";
import AddOrEdit from "../components/AddOrEdit";
import Detail from "../components/Detail";
import Email from "../components/Email";
import Tel from "../components/Tel";

function Router(props) {
  return useRoutes([
    {
      path: "/home",
      element: <Home />,
    },
    {
      path: "/about",
      element: <About />,
      children: [
        {
          path: "email",
          element: <Email />,
        },
        {
          path: "tel",
          element: <Tel />,
        },
        // 子路由的直接重定向,就是说进入about后默认进入email路由
        {
          path: "",
          element: <Navigate replace to="email" />,
        },
      ],
    },
    {
      path: "/add",
      element: <AddOrEdit />,
    },
    {
      path: "/detail/:id",
      element: <Detail />,
    },
    {
      path: "/edit/:id",
      element: <AddOrEdit />,
    },
    {
      path: "/",
      element: <Navigate replace to="/home" />,
    },
  ]);
}

export default Router;

app.jsx

路由的导入和使用,看着不舒服有点怪异

import { NavLink } from "react-router-dom";
import RouterConfig from "./router/router"

import "./css/App.css"

function App() {
  return (
    // 最外层容器
    <div id="app" className="container">
      {/* 导航栏 */}
      <nav className="navbar navbar-inverse navbar-fixed-top">
        <div className="container">
          <div className="navbar-header">
            <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
              <span className="sr-only">Toggle navigation</span>
              <span className="icon-bar"></span>
              <span className="icon-bar"></span>
              <span className="icon-bar"></span>
            </button>
            <div className="navbar-brand">学生管理系统</div>
          </div>
          <div id="navbar" className="collapse navbar-collapse">
            <ul className="nav navbar-nav">
              <NavLink to="/home" className="navigation">主页</NavLink>
              <NavLink to="/about" className="navigation">关于我们</NavLink>
            </ul>
            <ul className="nav navbar-nav navbar-right">
              <NavLink to="/add" className="navigation">添加学生</NavLink>
            </ul>
          </div>
        </div>
      </nav>
      {/* 匹配上的路由所对应的组件显示在这个位置 */}
      <div className="content">
        <RouterConfig/>
      </div>

    </div>
  );
}

export default App;

注意看上面的路由,子路由是配置在/about路径下的,对应的就是About组件,所以我们的子路由对应的子组件也是配置在about组件下的,需要注意的子路由对应的渲染子组件用的是Outlet,官方定义的展位符,后面子组件就渲染在这个位置

about.jsx

import React from "react";
import { NavLink, Outlet } from "react-router-dom";

function About() {
  return (
    <div className="about container">
      <h1 className="page-header">使用说明</h1>
      <p>通过此系统来熟悉 react 以及 react router 的使用</p>
      <p>联系方式</p>
      <NavLink to="/about/email" className="navigation">
        邮箱
      </NavLink>
      <NavLink to="/about/tel" className="navigation">
        电话
      </NavLink>
      <Outlet />
    </div>
  );
}

export default About;

文章作者: 吴俊杰
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 吴俊杰 !
  目录