构建一个react项目 - 超详细 - 路由集中管理(四)

134 阅读2分钟

前言

Snipaste_2022-11-08_10-12-22.png

  • react-router-dom第六个版本对route改动有点大,很多API都跟V5的使用方式不一样了,请注意
// 简单对比一下V5与V6的区别
<Switch> 重命名为 <Routes>
<Redirect> 重命名为 <Navigate>
`component/render``element` 替代
`useHistory``useNavigate` 替代
新API: `Outlet` - 主要用于子组件显示,作用类似于Vue中的`router-view`
  • 下面介绍的关于路由都是以V6版本为基准

目录结构介绍

app.js => { home, about => { subAbout, subAboutTwo }, dashboard }

Snipaste_2022-11-04_20-40-08.png

动态路由

app.js

import { HashRouter as Router, Routes, Route, NavLink, Redirect } from 'react-router-dom'

import Home from './pages/home'
import About from './pages/about'
import Dashboard from './pages/dashboard'

function App() {
  return (
    <div className="App">
      <div>
        <NavLink to='/' exact="true">Home</NavLink>
        <NavLink to='/about/*'>About</NavLink>
        <NavLink to='/dashboard'>Dashboard</NavLink>
      </div>
      <Routes>
        <Route exact path='/' element={<Home />}></Route>
        <Route exact path='/about/*' element={<About />}></Route>
        <Route exact path='/dashboard' element={<Dashboard />}></Route>
      </Routes>
    </div>
  );
}
export default App;

【注意】`about` 路径应该指定一个通配符匹配器,以允许子路由`path="/about/*"`的继续匹配。

about.js

import React from 'react'
import { Link, Routes, Route } from 'react-router-dom'

import SubAbout from '../subAbout'
import SubAboutTwo from '../subAboutTwo'

const About = (props) => {
    return (
        <div>
            <h1>About页面</h1>
            <Link to='subAbout'>去subAbout</Link>
            <Link to='subAboutTwo'>去subAboutTwo</Link>

            <Routes>
                <Route path='subAbout' element={<SubAbout />}>去subAbout</Route>
                <Route path='subAboutTwo' element={<SubAboutTwo />}></Route>
            </Routes>
        </div>
    )
}
export default About

【注意】二级路由的所有链接和路径也已更新为相对链接/路径而不是绝对链接/路径。

- RoutesRoute搭配
- 这也是react-route-dom@v5对路由的一种设计理念
    - 一级路由做统一集中配置和管理
    - 二级路由在各自的children的父组件做配置和管理

实现效果

Snipaste_2022-11-04_20-41-53.png

------------------------------------------ 分割线 ------------------------------------------

路由集中管理 + 懒加载
**
上述编写的路由太零散了,对于路由的管理不太友好。
可以参照 VUE 对路由进行集中管理

组件的加载也采用 -- 懒加载 -- 的方式

目录结构

src => router => index.js  // 集中编写路由

router => index.js

import { lazy } from 'react'
const routes = [
    {
        path: '/',
        name: 'Home',
        exact: true,
        element: lazy(() => import(('../pages/home'))),
        children: []
    },
    {
        path: '/dashboard',
        name: 'Dashboard',
        exact: true,
        element: lazy(() => import(('../pages/dashboard'))),
        children: []
    },
    {
        path: '/about/*',
        name: 'About',
        exact: true,
        element: lazy(() => import(('../pages/about'))),
        children: [
            {
                path: 'subAboutOne',
                name: 'SubAboutOne',
                element: lazy(() => import(('../pages/subAbout'))),
            },
            {
                path: 'subAboutTwo',
                name: 'SubAboutTwo',
                element: lazy(() => import(('../pages/subAboutTwo'))),
            }
        ]
    },
]

export default routes

app.js - 不管 children 的前提下


import { HashRouter as Router, Routes, Route, NavLink, Redirect } from 'react-router-dom'
import routes from './router'
import { React , Suspense } from 'react'
import { loadConfig } from 'browserslist';

function App() {
  return (
    <div className="App">
      <div>
        {
          routes.map((route, index) => {
            return (
              <NavLink to={route.path} key={index}> { route.name } </NavLink>
            )
          })
        }
      </div>
      <Routes>
          {
            routes.map((route, index) => {
              return (
                <Route exact={route.exact} path={route.path} element={
                  <Suspense fallback={
                    <div>Loading...</div>
                  }>
                    <route.element />
                  </Suspense>
                } key={index}></Route>
              )
            })
          }
      </Routes>
    </div>
  );
}

export default App;

about.js - 不使用 Outlet 前提下

import React from 'react'
import { Link, Routes, Route, Outlet } from 'react-router-dom'

import SubAbout from '../subAbout'
import SubAboutTwo from '../subAboutTwo'

const About = (props) => {
    return (
        <div>
            <h1>About页面</h1>
            <Link to='subAboutOne'>去subAbout</Link>
            <Link to='subAboutTwo'>去subAboutTwo</Link>

            <Routes>
                <Route path='subAboutOne' element={<SubAbout />}>去subAbout</Route>
                <Route path='subAboutTwo' element={<SubAboutTwo />}></Route>
            </Routes>
        </div>
    )
}

export default About

------------------------------------------ 分割线 ------------------------------------------

app.js - 循环遍历 children


import { HashRouter as Router, Routes, Route, NavLink, Navigate } from 'react-router-dom'
import routeItems from './router'
import { React , Suspense } from 'react'

function App() {

  const routerViews = (routerItems) => {
    if (routerItems && routerItems.length) {
      console.log('routerItems ---- ', routerItems);
      return routerItems.map(item => {
        return item.children && item.children.length ? (
          <Route key={item.path} path={item.path} element={
            <Suspense fallback={<div>Loading...</div>}>
              <item.element />
            </Suspense>
          }>
            {routerViews(item.children)}
            {
              item.redirect ? 
              (
                <Route path={item.path} element={<Navigate to={item.redirect} />}></Route>
              ) : 
              (
                <Route path={item.path} element={<Navigate to={item.children[0].path} />}></Route>
              )
            }
          </Route>
        ) : (
          <Route key={item.path} path={item.path} element={
            <Suspense fallback={<div>Loading...</div>}>
              <item.element />
            </Suspense>
          }></Route>
        )
      })
    }
  }

  return (
    <div className="App">
      <div>
        <div>
          {
            routeItems.map((route, index) => {
              return (
                <NavLink to={route.path} key={index}> { route.name } </NavLink>
              )
            })
          }
        </div>
      </div>
      <Routes>
        {
          routerViews(routeItems)
        }
      </Routes>
    </div>
  );
}

export default App;

about.js - 使用 Outlet

import React from 'react'
import { Link, Routes, Route, Outlet } from 'react-router-dom'

const About = (props) => {
    return (
        <div>
            <h1>About页面</h1>
            <Link to='subAboutOne'>去subAbout</Link>
            <Link to='subAboutTwo'>去subAboutTwo</Link>

            <Outlet />
        </div>
    )
}

export default About

------------------------------------------ 分割线 ------------------------------------------

// 使用useRoutes的方法