跳至主要內容

router

chanchaw大约 3 分钟react

安装

npx create-react-app react-router-pro
npm i
npm react-router-dom
# 切换到项目根目录下
npm run start
# pnpm 安装
pnpm add react-router-dom
# yarn
yarn add react-router-dom

自定义参数

定义路由时可插入自定义的参数,例如下面表示对用户组件没有权限要求,任何人都可以访问

{
    path: '/user',
    element: <User />
    meta: {
        auth: false
    }
}

获取当前路由

const { pathname } = useLocation()

路由守卫

在路由的属性 loader 上调用自定义的 AuthLoader

两种导航方式

声明式

import { Link } from "react-router-dom"
const Login = () => {
    return (
        <div className = 'login'>
            <span>登录页面</span>
            <Link to="/artical">文章</Link>
        </div>
    )
}
export default Login

编程式导航

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

const Artical = () => {
    const navigate = useNavigate();
    return (
        <div className = 'artical'>
            <span>文章页面</span>
            <button onClick={() => navigate('/login')}>跳转到登录</button>
        </div>
    )
}

export default Artical

嵌套路由

简单用法

带有二级的路由

import { createBrowserRouter } from 'react-router-dom'
import Login from '../page/login'
import Artical from '../page/artical'
import Layout from '../page/layout'
import Board from '../page/board'
import About from '../page/about'

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

export default router

以及路由对应的组件如下。特别注意标签 outlet,其下的子组件会显示在该位置,可通过两个 link 按钮跳转,或者在浏览器地址栏中直接输入到二级路由

import { Outlet, Link } from "react-router-dom"

const Layout = () => {
    return (
        <div>
            <h1>我是框架页</h1>
            <Link to="/board">面板</Link>
            <Link to="/about">关于</Link>
            <Outlet />
        </div>
    )
}

export default Layout

默认二级路由

两种路由模式

react两种路由模式
react两种路由模式

两种模式只是在创建路由对象时使用不同的方法即可

案例

最简 - 创建路由

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { createBrowserRouter, RouterProvider } from 'react-router-dom'

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <RouterProvider router={router}>
    </RouterProvider>
  </React.StrictMode>
);
reportWebVitals();

最佳实践 - 创建路由

在项目根目录下创建目录 page 用于存放每个组件,同级别下创建 router 目录作为路由目录

路由目录结构
路由目录结构

两个组件:Login , Artical 代码如下

const Artical = () => {
    return (
        <div className = 'artical'>
            <span>文章页面</span>
        </div>
    )
}

export default Artical

const Login = () => {
    return (
        <div className = 'login'>
            <span>登录页面</span>
        </div>
    )
}

export default Login

路由文件 src/router/index.js 代码如下 - 可通过 basename 添加项目名称

import { createBrowserRouter } from 'react-router-dom'
import Login from '../page/login'
import Artical from '../page/artical'

const router = createBrowserRouter([
    {
        path: '/login',
        element: <Login />
    },
    {
        path: '/artical',
        element: <Artical />
    }
],{
    basename: '/app'
})

export default router

项目根 js (src/index.js)中引用路由

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import { RouterProvider } from 'react-router-dom'
import router from './router'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <RouterProvider router={router}>
    </RouterProvider>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

导航传参

下图右边的传参方式要在 artical 路由后面添加占位符 /artical/:id/:name

原页面跳转时传参

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

const Artical = () => {
    const navigate = useNavigate();
    return (
        <div className = 'artical'>
            <span>文章页面</span>
            <button onClick={() => navigate('/login?id=1001&name=nick')}>跳转到登录</button>
        </div>
    )
}
export default Artical

新页面接受参数

import { Link, useSearchParams } from "react-router-dom"

const Login = () => {
    const [params] = useSearchParams()
    const id = params.get('id')
    const name = params.get('name')
    
    return (
        <div className = 'login'>
            <span>登录页面</span>
            <Link to="/artical">文章</Link>
            <h1>参数</h1>
            <div>id:{id}</div>
            <div>name:{name}</div>
        </div>
    )
}

export default Login

路由跳转的多种方式

<NavLink to="/react"></NavLink>
<Link to="/react"></Link>

// Navigate 重定向组件
<Route path='/vite' element={<Navigate to={'/react'} />}></Route>
function Vue() {
return <h2>欢迎学习Vue课程{<Navigate to={'/react'} />}</h2>
}

// 组件中跳转
const navigate = useNavigate();
navigate('/react')

// 404
<Route path='*' element={<NotFound />}</Route>

参数相关

下面代码中 :idurl 参数

{
    path:'/order/:id'
    element: <Order />
}

// 通过下面方式获取参数
const params = useParams()
const orderId = params.id