NipGeihou's blog NipGeihou's blog
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档

NipGeihou

我见青山多妩媚,料青山见我应如是
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档
  • nodejs

  • css

  • 最佳实践

  • TypeScript

  • ajax

  • JavaScript

  • 前端工程化

  • React

    • React - 入门
    • React - Redux
    • ReactRouter
      • 前端路由
      • 安装
      • 快速开始
      • 路由导航
        • 声明式 - Link
        • 编程式导航 - useNavigate
      • 导航传参
        • searchParams
        • params
      • 嵌套路由(二级路由)
        • 创建页面
        • 配置
        • 完善一级路由页面
        • 配置默认二级路由
      • 404路由
      • 路由模式
      • 路由鉴权
      • 参考
    • 规范
  • nextjs

  • Flutter

  • 笔记

  • 前端
  • React
NipGeihou
2024-08-20
目录

ReactRouter

# 前端路由

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

const routes = [
  {
    path: '/about',
    component: About,
  },
  {
    path: '/article',
    component: Article,
  },
]

# 安装

# 安装最新的ReactRouter包
npm i react-router-dom

# 快速开始

浅使

index.js

import React from 'react'
import ReactDOM from 'react-dom/client'

const router = createBrowserRouter([
  {
    path:'/login',
    element: <div>登录</div>
  },
  {
    path:'/article',
    element: <div>文章</div>
  }
])

ReactDOM.createRoot(document.getElementById('root')).render(
  <RouterProvider router={router}/>
)
  • /src/page 目录下创建页面文件夹,如 Login 、 Article
  • 页面文件夹中创建 index.js
const Article = () => {
  return <div>我是文章页</div>
}
export default Article
  • 创建 /src/route 目录,并创建文件 index.js
import Login from '../page/Login';

import Article from '../page/Article';

import { createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/login',
    element: <Login />
  },
  {
    path: '/article',
    element: <Article />
  }
])

export default router;
  • 应用入口文件( /src/index.js )渲染 RouterProvider
...

// 1. 导入路由router
import router from './router'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        {/*  2. 路由绑定 */}
    	<RouterProvider router={router}/>
    </React.StrictMode>
);

# 路由导航

# 声明式 - Link

Link v6.26.1 | React Router (opens new window)

声明式导航是指通过在模版中通过 <Link/> 组件描述出要跳转到哪里去,比如后台管理系统的左侧菜单通常使用这种方式进行

<Link to="/article">文章</Link>

# 编程式导航 - useNavigate

useNavigate v6.26.1 | React Router (opens new window)

编程式导航是指通过 useNavigate 钩子得到导航方法,然后通过调用方法以命令式的形式进行路由跳转,比如想在登录请求完毕之后跳转就可以选择这种方式,更加灵活

import { useNavigate } from "react-router-dom";

const Login = () => {
  const navigate = useNavigate()
  return (
    <div>
      我是登录页
      <button onClick={() => navigate('/article')}>跳转到文章页</button>
    </div>
  )
}

export default Login;

# 导航传参

以下演示 useNavigate 方式, Link 同理

# searchParams

useSearchParams v6.26.1 | React Router (opens new window)

传递

navigate('/article?id=1001&name=jack')

接收

import * as React from "react";
import { useSearchParams } from "react-router-dom";

function App() {
  let [searchParams] = useSearchParams()
  let id = params.get('id')

  return (
    <div>
      ...
    </div>
  );
}

# params

useParams v6.26.1 | React Router (opens new window)

路由配置

/src/router/index.js :添加占位符 :id

...
const router = createBrowserRouter([
...
  {
    path:'/article/:id',
    element: <div>文章</div>
  }
])
...

传递

navigate('/article/1001')

接收

const Article = () => {
  const params = useParams()
  const id = params.id

  return <div>我是文章页{id}</div>
}
export default Article

# 嵌套路由(二级路由)

在一级路由中又内嵌了其他路由,这种关系就叫做嵌套路由,嵌套至一级路由内的路由又称作二级路由,例如:

image-20240820120306705

# 创建页面

  • /src/Layout/index.js :一级路由
const Layout = () => {
  return (
    <div>我是一级路由</div>
      <Outlet />
  )
}
export default Layout
  • /src/About/index.js :二级路由
  • /src/Board/index.js :二级路由

# 配置

/src/router/index.js

import Layout from '../page/Layout';
import Board from '../page/Board';
import About from '../page/About';

import { createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      {
        path: 'board',
        element: <Board />
      },
      {
        path: 'about',
        element: <About />
      }
    ]
  },
])

export default router;

路由懒加载

上述写法会在首次打开网页时加载所有页面的资源,会导致加载速度慢,使用 lazy 函数和 Suspense 组件可实现懒加载

import Layout from '../page/Layout';
- import Board from '../page/Board';
- import About from '../page/About';
+ const Publish = lazy(() => import('@/pages/Board'))
+ const About = lazy(() => import('@/pages/About'))

import { createBrowserRouter } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      {
        path: 'board',
-        element: <Board />
+        element: (
+          <Suspense fallback={'加载中'}>
+            <Board />
+          </Suspense>
+        )
      },
....

# 完善一级路由页面

const Layout = () => {
  return (
    <div>我是一级路由
      <Link to="/board">面板</Link>
      <Link to="/about">关于</Link>
      { /* 配置二级路由的出口 */}
      <Outlet />
    </div>
  )
}
export default Layout

PS:跳转到的页面为 /board ,而不是 /layout/board

# 配置默认二级路由

只需要在二级路由的位置去掉 path ,设置 index 属性为 true

children: [
  {
-    path: 'board',
+	index: true
    element: <Board />
  },
  {
    path: 'about',
    element: <About />
  }
]

原来跳转到 /board 要改成跳转 /

- <Link to="/board">面板</Link>
+ <Link to="/">面板</Link>

# 404 路由

  1. 准备一个 NotFound 组件
  2. 在路由表数组的末尾,以 * 作为路由 path 配置路由
  {
    path: '*',
    element: <NotFound />
  }

# 路由模式

各个主流框架的路由常用的路由模式有俩种,history 模式和 hash 模式,ReactRouter 分别由 createBrowerRouter 和 createHashRouter 函数负责创建

路由模式 url 表现 底层原理 是否需要后端支持
history url/login history 对象 + pushState 事件 需要
hash url/#/login 监听 hashChange 事件 不需要

route/index.js

...
const router = createBrowserRouter([
  ...
])

export default router;

# 路由鉴权

业务背景:封装 AuthRoute 路由鉴权高阶组件,实现未登录拦截,并跳转到登录页面 实现思路:判断本地是否有 token,如果有,就返回子组件,否则就重定向到登录 Login

实现步骤

  1. 在 components 目录中,创建 AuthRoute/index.jsx 文件
  2. 登录时,直接渲染相应页面组件
  3. 未登录时,重定向到登录页面
  4. 将需要鉴权的页面路由配置,替换为 AuthRoute 组件渲染

代码实现 components/AuthRoute/index.jsx

import { getToken } from '@/utils'
import { Navigate } from 'react-router-dom'

const AuthRoute = ({ children }) => {
  const isToken = getToken()
  if (isToken) {
    return <>{children}</>
  } else {
    return <Navigate to="/login" replace />
  }
}

export default AuthRoute

src/router/index.jsx

import { createBrowserRouter } from 'react-router-dom'

import Login from '@/pages/Login'
import Layout from '@/pages/Layout'
import AuthRoute from '@/components/Auth'


const router = createBrowserRouter([
  {
    path: '/',
    element: <AuthRoute><Layout /></AuthRoute>,
  },
  {
    path: '/login',
    element: <Login />,
  },
])

export default router

# 参考

Home v6.26.1 | React Router (opens new window)

上次更新: 2024/08/28, 13:22:10
React - Redux
规范

← React - Redux 规范→

最近更新
01
元器件
05-23
02
iSCSI服务搭建
05-10
03
磁盘管理与文件系统
05-02
更多文章>
Theme by Vdoing | Copyright © 2018-2025 NipGeihou | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式