Skip to content

React Router

介绍

React Router 是一个用于处理路由的库,它提供了一套用于处理路由的组件和 API,使得在 React 应用中实现路由功能更加方便和灵活。

安装

bash
npm i react-router-dom@6
详细说明

v17 -> react-router-dom@5 v18 -> react-router-dom@6

项目搭建

bash
/src
  /router
    index.jsx
  App.jsx
  main.jsx
jsx
import { createHashRouter } from 'react-router-dom'
import React, { Suspense } from 'react'

import Home from '../views/Home.jsx'
const About = React.lazy(() => import('../views/About.jsx'))

const router = createHashRouter([
  {
    path: '/',
    element: <Home />,
  },
  {
    path: '/about',
    element: (
      <Suspense fallback={<div>Loading...</div>}>
        <About />
      </Suspense>
    ),
  },
])

export default router
jsx
import { RouterProvider } from 'react-router-dom'
import router from './router'

function App() {
  return <RouterProvider router={router}></RouterProvider>
}

export default App

路由懒加载

如上,使用 React.lazy 引入组件,还可以使用 Suspense 包裹,指定 fallback 为加载提示组件。

路由模式

Hash 模式

jsx
import { createHashRouter } from 'react-router-dom'

const router = createHashRouter([
  // ...
])

HTML5 模式

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

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

Memory 模式

jsx
import { createMemoryRouter } from 'react-router-dom'

const router = createMemoryRouter(routes, {
  // ...
})

路由导航

声明式

jsx
import { Link } from 'react-router-dom'

function Home() {
  return (
    <div>
      <h1>Home</h1>
      <Link to="/about">关于页</Link>
    </div>
  )
}

export default Home

编程式

jsx
import { useNavigate } from 'react-router-dom'

function Home() {
  const navigate = useNavigate()

  return (
    <div>
      <h1>Home</h1>
      <button onClick={() => navigate('/about')}>关于页</button>
    </div>
  )
}

export default Home

路由传参 & 接参

searchParams

jsx
<Link to={`/user?id=12&name=vfanlee`}>User</Link>
jsx
import { useSearchParams } from 'react-router-dom'

const [params] = useSearchParams()
const id = params.get('id')
const name = params.get('name')

params

jsx
{
  path: '/user/:id/:name',
  element: <User />
}
jsx
import { useParams } from 'react-router-dom'

const params = useParams()
const id = params.id
const name = params.name

嵌套路由

  1. 在路由配置文件中通过 children 属性配置子路由
  2. 在父组件中通过 <Outlet> 组件渲染子路由
jsx
{
  path: '/',
  element: <Layout />,
  children: [
    {
      path: '/home',
      element: <Home />
    },
    {
      path: '/about',
      element: <About />
    }
  ]
}
jsx
import { Outlet } from 'react-router-dom'

function Layout() {
  return (
    <>
      <h1>Layout</h1>
      <Outlet />
    </>
  )
}

export default Layout

默认路由

嵌套路由时,指定某个子路由为默认路由,可通过 index: true 指定默认路由:

jsx
{
  path: '/',
  element: <Layout />,
  children: [
    {
      index: true,
      element: <Home />
    },
    {
      path: '/about',
      element: <About />
    }
  ]
}

亦或者,定义 path 为空字符串:

jsx
{
  path: '/',
  element: <Layout />,
  children: [
    {
      path: '',
      element: <Home />
    },
    {
      path: '/about',
      element: <About />
    }
  ]
}

404 路由

jsx
{
  path: '*',
  element: <NotFound />
}

路由激活

在 React Router v6 中,获取当前激活路由的最佳方式是使用 <NavLink> 组件或 useLocation 钩子。

这是最简单的方式,<NavLink> 会自动为当前激活的链接添加 active 类(可以自定义)。

jsx
import { NavLink } from 'react-router-dom'

function Navbar() {
  return (
    <nav>
      <NavLink to="/home" className={({ isActive }) => (isActive ? 'active' : '')}>
        Home
      </NavLink>
      <NavLink to="/about" className={({ isActive }) => (isActive ? 'active' : '')}>
        About
      </NavLink>
    </nav>
  )
}

你可以在 CSS 里定义 .active 来控制高亮样式:

css
.active {
  color: #00dc82;
  font-weight: bold;
}

使用 useLocation 钩子手动判断当前路径

如果你不使用 <NavLink>,可以用 useLocation 获取当前路径名,再手动判断:

jsx
import { useLocation, Link } from 'react-router-dom'

function Navbar() {
  const location = useLocation()

  return (
    <nav>
      <Link to="/home" className={location.pathname === '/home' ? 'active' : ''}>
        Home
      </Link>
      <Link to="/about" className={location.pathname === '/about' ? 'active' : ''}>
        About
      </Link>
    </nav>
  )
}

注意:location.pathname 是完整路径,不带 query 或 hash。

带参数或嵌套路由

如果你用的是动态路径,比如 /users/:id,可以使用 useMatch 来匹配当前路由:

jsx
import { useMatch, Link } from 'react-router-dom'

function Navbar() {
  const match = useMatch('/users/:id')

  return (
    <Link to="/users/123" className={match ? 'active' : ''}>
      User Detail
    </Link>
  )
}

基于 MIT 许可发布