likes
comments
collection
share

react-router-dom v6应用

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

react-router-dom

react-router-dom v6应用

作为一名近几年一直在用Vue生态的前端 [ 小程序,UniApp,Sass ]包括一些H5 甚至开发桌端应用也是用的Vue [nwjs打包,Electron插件打包]

对于react基本上每隔一段会看,毕竟是前端中很重要的一个框架,工作中不用可以 但是不能不会 起码到用到的时候能以最快速度适应

一直认为react-router-dom v5 特别麻烦 特别是跟vue-router一对比后 不过两个框架随着升级 写法越来越像了 比如: hook函数 , pinia与mobx , vue-router与react-router-dom v6

react-router-dom v6应用

V6版本抽离路由表

不好的

    // 写法繁杂  不灵活   随着业务增多代码阅读困难
    <Routes>
        <Route path="/a" element={<A />}>
          <Route path="/a/child1" element={<Achild1 />} />
          <Route path="/a/child2" element={<Achild2 />} />
        </Route>
        <Route path="/b" element={<B />} />
        <Route path="/c" element={<C />} />
    </Routes>

抽离路由表 router/routes.js

/**
 *  典型的路由嵌套结构 
 *
 */ 

import { Navigate } from 'react-router-dom'
import { lazy } from 'react'

export const routes = [
    {
        path:'/',
        element:()=><Navigate to="/a/achild1" />,
        meta:{
            name:"A页面",
            isLogin:false
        }
    },
    {
        path:'/a',
        element:lazy(()=>import('./../components/a')),
        children:[
            {
                path:'/a/achild1',
                element:lazy(()=>import('./../components/achild/achild1')),
                meta:{
                    name:"A页面",
                    isLogin:false
                }
            },
            {
                path:'/a/achild2',
                element:lazy(()=>import('./../components/achild/achild2')),
                meta:{
                    name:"A页面",
                    isLogin:false
                }
            },
        ],
        meta:{
            name:"A页面",
            isLogin:false
        }
    },
    {
        path:'/b',
        element:lazy(()=>import('./../components/b')),
        children:[],
        meta:{
            name:"B页面",
            isLogin:true
        }
    },
    {
        path:'/c',
        element:lazy(()=>import('./../components/c')),
        children:[],
        meta:{
            name:"C页面",
            isLogin:true
        }
    },
    {
        path:'/login',
        element:lazy(()=>import('./../components/login')),
        children:[],
        meta:{
            name:"登录",
            isLogin:false
        }
    }
]

既然能拿到路由表 无非就是生成 < Routes />嵌套结构 需要的信息 在路由表中都能拿到 不管多少子集路由 一个递归函数即可

    <Routes>
        <Route path="/a" element={<A />}>
          <Route path="/a/child1" element={<Achild1 />} />
          <Route path="/a/child2" element={<Achild2 />} />
        </Route>
        <Route path="/b" element={<B />} />
        <Route path="/c" element={<C />} />
    </Routes>

router/index.js

import { routes } from "./routes";
import {
  Routes,
  Route,
  useLocation,
  useParams,
  useSearchParams,
  useNavigate,
  Navigate,
} from "react-router-dom";
import { Suspense } from "react";
/**
 * 处理组件
 * @params { Route } props
 * 根据不同的业务 处理组件不用的逻辑等
 * */ 
const Element = (props) => {
  const {
    element: Component,
    meta: { name, isLogin },
  } = props;
//   将路由信息传递
  const navigate = useNavigate();
  const location = useLocation();
  const params = useParams();
  const [usp] = useSearchParams();
//   权限的demo等
//   if (name) document.title = name;
//   if (isLogin) {
//     if (!window.sessionStorage.getItem("login")) {
//       return <Navigate to="/login"></Navigate>;
//     }
//   }
  return (
    <Component
      navigate={navigate}
      location={location}
      params={params}
      usp={usp}
    />
  );
};
/**
 * 创建 Route
 * @params { Array } routes
 * 
 * */ 
export const createElement = (routes) => {
  return (
    <>
      {routes.map((item) => {
        const { path, children } = item;
        return (
          <Route key={item.path} path={path} element={<Element {...item} />}>
            {/* 有子集 , 递归调用 */}
            {Array.isArray(children) ? createElement(children) : null}
          </Route>
        );
      })}
    </>
  );
};

export default function RouterView() {
  return (
    <Suspense fallback="正在加载中...">
      <Routes>{createElement(routes)}</Routes>
    </Suspense>
  );
}