1:router.ts,加载页面,设置routerBefore拦截函数
import PublicRouters from "./public-routers";
import HomeRouters from "./home-routers";
import {getLocalStorage} from "../utils";
import {onRouteBeforeRule, RouteObjectRule} from "../react-router-dom6-guard";
const routes: RouteObjectRule[] = [
{
path: '*',
redirect: '/home',
},
{
path: 'login',
meta: {
title: '登录',
},
page: () => import("../pages/login"),
},
{
path: 'register',
meta: {
title: '注册',
},
page: () => import("../pages/register"),
},
{
path: 'home',
page: () => import("../pages/Home/home"),
meta: {
auth: true
},
children: [
{
index: true, //设置默认
path: '*',
meta: {
title: '个人主页',
},
page: () => import('../pages/Home/index/index')
},
{
path: 'organization',
meta: {
title: '组织机构管理',
},
page: () => import('../pages/Home/organization/index')
},
],
},
];
//根据路径获取路由
const checkAuth = (routers: Array<RouteObjectRule>, path: string) => {
for (const data of routers) {
if (data.path === path) return data;
if (data.children) {
const res = checkAuth(data.children, path);
if (res) return res;
}
}
return null
};
// 如果单独的页面需要设置权限等, 在outlet前根据路径,获取路由的详情,设置权限
const checkRouterAuth = (path: string) => checkAuth(routes, path);
//全局路由守卫
const onRouteBefore: onRouteBeforeRule = (meta, to) => {
const {auth, title} = meta;
if (title) { // 动态修改页面title
document.title = title || '统一中心管理';
}
console.log('to' , to)
return to;
// token权限验证
return (auth && !getLocalStorage('access_token')) ? '/login' : to;
};
export default routes;
export {
onRouteBefore,
checkRouterAuth,
}
2:react-router-dom6-guard.tsx ,reactRouterdom6的路由统一封装,用到了useRouters
import {useRoutes, RouteObject, Navigate, useLocation} from 'react-router-dom';
import React, {Suspense} from "react";
interface FunctionRule {
(): any
}
//meta规则
interface MetaRule {
auth ?: boolean, //是否需要登录验证
title ?: string, //页面title
[name:string] : string | boolean, //其他参数
}
//单个路由规则
interface RouteObjectRule extends RouteObject {
children ?: RouteObjectRule[], //子路由
page ?: FunctionRule, //route导入页面的对象
path ?: string, //页面路径
redirect ?: string, //重定向地址 ,常用于设置页面默认地址
meta ?: MetaRule, //页面参数
}
interface onRouteBeforeRule<meta = MetaRule , to = string> {
(meta : meta, to : to) : any | never
}
type LoadingEleRule = React.ReactNode;
interface GuardRule {
routers : RouteObjectRule[],
onRouterBefore ?: onRouteBeforeRule,
loading ?: LoadingEleRule,
}
let onRouterBefore : onRouteBeforeRule;
let RouterLoading : FunctionRule;
//路由导航,设置redirect重定向 和 auth权限
function Guard ({ element, meta}) {
const { pathname } = useLocation();
const nextPath = onRouterBefore ? onRouterBefore(meta ,pathname) : pathname;
if (nextPath && nextPath !== pathname) {
element = <Navigate to={nextPath} replace={true}/>;
}
return element;
}
// 路由懒加载
function lazyLoadRouters(page, meta){
meta = meta || {};
const LazyElement = React.lazy(page);
const GetElement = ()=> {
return (
<Suspense fallback={<RouterLoading/>}>
<LazyElement/>
</Suspense>
);
};
return <Guard element={<GetElement/>} meta={meta}/>;
}
function transRoutes(routes : RouteObjectRule[]) {
const list = [];
routes.forEach(route => {
const obj = { ...route };
if (obj.redirect) {
obj.element = <Navigate to={obj.redirect} replace={true} />
}
if (obj.page) {
obj.element = lazyLoadRouters(obj.page, obj.meta)
}
if (obj.children) {
obj.children = transRoutes(obj.children)
}
['redirect','page','meta'].forEach(name => delete obj[name]);
list.push(obj)
});
return list
}
export type {
RouteObjectRule,
MetaRule,
FunctionRule,
onRouteBeforeRule,
LoadingEleRule,
}
function RouterGuard(params : GuardRule){
onRouterBefore = params.onRouterBefore;
RouterLoading = ()=> params.loading || <></>;
return useRoutes(transRoutes(params.routers));
}
export default RouterGuard;
3:app.ts , 引入封装的routerdom6guard,传入router数组
import React from 'react';
import routes, {onRouteBefore} from "./routers";
import {BrowserRouter, Route} from "react-router-dom";
import {setLocalStorage, getLocalStorage} from "./utils";
import store, {actions} from './redux';
import RouterGuard from './react-router-dom6-guard';
import Loading from './components/Loading';
const App = function () {
const UserInfo: any = getLocalStorage('userInfo');
const access_token: any = getLocalStorage('access_token');
if (UserInfo) {
store.dispatch(actions.setUserInfo(JSON.parse(UserInfo)));
store.dispatch(actions.setToken(access_token));
}
window.addEventListener('beforeunload', (event) => {
setLocalStorage('userInfo', JSON.stringify(store.getState().userInfo));
setLocalStorage('access_token', store.getState().access_token);
});
const baseUrl = `/${process.env.PUBLIC_URL}` || '/'; //路由前缀 = 打包路径 如:uauth, 解决打包项目后,刷新404等问题
return (
<BrowserRouter basename={baseUrl}>
<RouterGuard
routers={routes}
onRouterBefore={onRouteBefore}
loading={<Loading/>}
/>
</BrowserRouter>
);
};
export default App;
4:index.ts ,没啥特殊操作
import React from 'react';
import ReactDOM from 'react-dom';
import zhCN from 'antd/lib/locale/zh_CN';
import './assets/ali-fonts/iconfont.css';
import 'antd/dist/antd.less';
import './css/style.scss';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './redux';
import {Provider} from 'react-redux';
import {ConfigProvider} from 'antd';
ReactDOM.render(
<Provider store={store}>
<ConfigProvider locale={zhCN}>
<App/>
</ConfigProvider>
</Provider>,
document.getElementById("root"),
);
reportWebVitals();
5:.env文件配置 , 可以解决打包项目后,刷新404等问题
PUBLIC_URL = 'uauth' //设置为打包的文件夹名称,也是路由前缀路由,加在BrowserRouter /HashRouter的basename上
6:项目未写完,需要请酌情copy
项目下载地址