likes
comments
collection
share

React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404

作者站长头像
站长
· 阅读数 3

前言

  • 前端路由
    • 一个路径path 对应 一个组件component 当我们在浏览器中访问一个 path 的时候,path对应的组件会在页面中进行渲染;

一、准备路由开发环境

使用路由我们还是采用CRA创建项目的方式进行基础环境配置;

  • 创建具有 路由 项目的 步骤
    • 创建项目并安装所有依赖:
      • npm create-react-app xxx(项目名称)
    • 安装最新的 ReactRouter 包:
      • npm i react-router-dom
    • 启动项目:
      • npm run start

二、创建并注入路由实例

2.1 准备工作

  • src 目录下新建目录:
    • router 目录:
      • 创建 index.js 文件(初始化路由);
    • pages 目录:
      • 创建组件;
  • 创建组件的时候,组件名称一定是首字母大写的;

React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404

2.2 创建路由实例

  • 目标文件
    • src/router/index.js
// 导入创建路由的函数
import { createBrowserRouter } from 'react-router-dom';

// 创建router路由实例对象,并配置路由对应关系(路由数组)
const router = createBrowserRouter([
  {
    // 需要访问的路径
    path: '/',
    // 和路径对应的组件
    // 和 Vue 不同的是,此处是使用 element 接收 组件 或 jsx 的
    // 此处写 jsx 是为了演示,在实际开发中,这里写的是组件
    element: <div>Login Page</div>
  }
]);

export default router;

2.3 注入路由实例

  • 目标文件
    • src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import router from './router';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    {/* 使用 redux 的时候,需要用 Provider 包裹 RouterProvider */}
    {/* 路由绑定,注入路由实例对象 */}
    <RouterProvider router={router} />
  </React.StrictMode>
);

三、路由导航

  • 什么是路由导航?
    • 路由系统中的多个路由之间需要进行 路由跳转,并且在跳转的同时有可能需要 传递参数进行通信

3.1 声明式导航

  • 在模板中通过 <Link /> 组件描述出要跳转到哪里(通过to属性进行描述),比如后台管理系统在左侧的菜单通常使用这种方式进行跳转;
  • 语法说明
    • 通过 给组件的 to属性 指定 要跳转的 路由path,组件会被渲染为浏览器支持的a链接;
    • 如果需要 传参 直接通过 字符串拼接 的方式 拼接参数 即可;
    import { Link } from 'react-router-dom';
    
    <Link to={'path路径'}>XXX</Link>
    
  • 使用场景:
    • 菜单居多;
  • 代码展示:
    • 优化 Login、Article组件;
    • Login
      import { Link } from 'react-router-dom';
      
      const Login = () => {
        return (
          <div>
            <div>登陆页面</div>
            <Link to="/article">文章页面</Link>
          </div>
        );
      };
      
      export default Login;
      
    • Article
      import { Link } from 'react-router-dom';
      
      const Article = () => {
        return (
          <div>
            <div>文章页面</div>
            <Link to={'/login'}>登录页面</Link>
          </div>
        );
      };
      
      export default Article;
      

3.2 编程式导航

  • 通过 useNavigate 钩子得到的导航方法,然后通过 调用方法 以 命令式 的 形式 进行路由跳转。
    • 比如想在登录请求完毕之后跳转就可以选择这种方式,更加灵活;
  • 语法说明
    • 通过调用 navigate 方法传入地址 path 实现跳转;
    import { useNavigate } from 'react-router-dom';
    
    // useNavigate 的调用必须写在组件里面;
    // navigate接受一个参数:需要跳转到的路径
    const navigate = useNavigate();
    
  • 使用场景:
    • 写在逻辑代码里面;
  • 代码展示:
    • 优化 Login、Article组件;
    • Login
      import { Link, useNavigate } from 'react-router-dom';
      
      const Login = () => {
        const navigate = useNavigate();
        return (
          <div>
            <div>登陆页面</div>
            {/* 声明式 */}
            {/* <Link to={'/article'}>文章页面</Link> */}
            
            {/* 编程式 */}
            <button onClick={() => navigate('/article')}>跳转到文章页面</button>
          </div>
        );
      };
      
      export default Login;
      
    • Article
      import { Link, useNavigate } from 'react-router-dom';
      
      const Article = () => {
        const navigate = useNavigate();
        return (
          <div>
            <div>文章页面</div>
            {/* 声明式 */}
            {/* <Link to="/login">登录页面</Link> */}
            
            {/* 编程式 */}
            <button onClick={() => navigate('/login')}>跳转登录页面</button>
          </div>
        );
      };
      
      export default Article;
      

四、路由导航传参

编程式导航传参 为例,声明式导航也一样;

4.1 searchParams 传参

  • 传参
    • 字符串拼接(查询字符串)
    • 代码展示:
      import { useNavigate } from 'react-router-dom';
      
      const navigate = useNavigate();
      
      navigate('/article?userId=1001&articleId=abcd');
      
  • 接收参数:
    • 调用 useSearchParams 钩子函数,从返回结果(数组)中解构出params对象,调用该对象的get方法,将需要的 参数名字 传递给get方法即可;
      import { useSearchParams } from 'react-router-dom';
      
      const [params] = useSearchParams();
      
      console.log(params.get('userId'));
      

4.2 params 传参

  • 传参
    • 语法
      • 需要对路由规则数组进行改造(和Vue一样,用 /:参数名 进行占位);
        const router = createBrowserRouter([
          {
            // 需要访问的路径
            path: '/login/:userId/:likeId',
            // 和路径对应的组件
            // 和 Vue 不同的是,此处是使用 element 接收 组件 或 jsx 的
            element: <Login />
          }
        ]);
        
    • 代码展示:
      import { useNavigate }  from 'react-router-dom';
      
      const navgiate = useNavigate();
      
      navigate('/article/1001/abcd');
      
  • 接收参数
    • 语法
      • 导入并调用 useParams 钩子函数,该钩子函数的返回值是个对象,传递的参数在这个对象中,通过点语法进行读取;
    • 代码展示:
      import { useParams } from 'react-router-dom';
      
      const params = useParams();
      
      console.log(params);
      
    React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404

五、嵌套路由配置

  • 嵌套路由:
    • 在一级路由中又内嵌了其他路由,这种关系就叫做嵌套路由
    • 嵌套至一级路由内的路由又称为二级路由React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404
  • 实现步骤
    • 使用 children属性(属性值是个** **) 配置 路由 嵌套关系
    • 使用 <Outlet />组件 配置 二级路由 渲染位置(二级路由出口);
      • 这个组件在哪里,二级路由渲染的位置就在哪里;
  • 代码展示:
    • 创建三个组件Layout(一级路由)、About(二级路由)、Board(二级路由)
      // About 组件
      const About = () => {
        return <div>我是关于组件</div>;
      };
      export default About;
      
      // Board 组件
      const Board = () => {
        return <div>我是面板组件</div>;
      };
      export default Board;
      
      
      // Layout 组件
      import { Link, Outlet, useNavigate } from 'react-router-dom';
      const Layout = () => {
        const navigate = useNavigate();
        return (
          <div>
            <div>一级路由</div>
      
            <Link to="/layout/board">面板</Link>
            <button onClick={() => navigate('/layout/about')}>关于</button>
            
            {/* 二级路由出口 */}
            <Outlet />
          </div>
        );
      };
      export default Layout;
      
    • 目标文件:router/index.js
      // 只写部分代码
      import Layout from '../pages/Layout';
      import About from '../pages/About';
      import Board from '../pages/Board';
      
      const router = createBrowserRouter([
        {
          path: '/layout',
          element: <Layout />,
          children: [
            {
              path: 'about',
              element: <About />
            },
            {
              path: 'board',
              element: <Board />
            }
          ]
        },
      ]);
      
  • 效果演示:
    • React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404

六、默认二级路由配置

  • 当访问一级路由的时候,默认的二级路由组件可以得到渲染,只需要在二级路由的位置去掉path设置index属性为true 即可;
    • Vue中是将二级路由的path置为空串;
  • 代码展示:
    const router = createBrowserRouter([
        {
            path: '/layout',
            element: <Layout />,
            children: [
                {
                    // 设置默认二级路由,一级路由访问的时候,它也能得到渲染
                    // path: 'about',
                    // 访问的时候,直接访问 /layout 即可
                    index: true,
                    element: <About />
                },
                {
                    path: 'board',
                    element: <Board />
                }
            ]
        }
    ]);
    
    React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404
  • 效果演示:
    • React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404

七、404路由配置

  • 场景
    • 当浏览器输入的url地址在整个路由配置中都找不到对应的path,为了用户体验,可以使用404兜底组件进行渲染;
  • 实现步骤
    • 准备一个NotFound组件;
    • 在路由规则数组的末尾,以 * 作为路由path配置路由;
  • 代码展示:
    • 目标文件:router/index.js
    import NotFound from '../pages/NotFound';
    
    const router = createBrowserRouter([
        ...,
        {
            path: '*',
            element: <NotFound />
        }
    ]);
    

八、路由模式

  • 各个主流框架的路由常用的路由模式有两种,history模式hash模式
  • ReactRouter分别由:createBrowerRoutercreateHashRouter 函数负责创建;
路由模式url表现底层原理是否需要后端支持
historyurl/loginhistory对象 + pushState事件需要
hashurl/#/login监听hashChange事件不需要
  • 更换创建路由实例的方法即可;
    • React全家桶 - 【ReactRouter】- 基础使用、路由导航、路由传参、嵌套路由、二级路由配置、路由模式、404