react-router-dom6路由守卫

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

项目下载地址

react-router-dom v6 中,路由守卫(Route Guards)的实现方式有所改变。v6 中引入了新的 `useNavigate` 钩子函数来处理导航,以及 `<Routes>` 组件来定义路由规则。 要实现路由守卫,你可以使用 `useNavigate` 钩子函数来进行导航,并结合 `<Routes>` 组件的 `element` 属性来定义需要守卫的路由组件。下面是一个简单的示例: ```jsx import { useNavigate, Routes, Route } from 'react-router-dom'; // 自定义的路由守卫组件 function PrivateRoute({ element: Element, ...rest }) { const navigate = useNavigate(); const isAuthenticated = /* 判断用户是否已登录的逻辑 */; if (!isAuthenticated) { // 如果用户未登录,导航到登录页 navigate('/login'); return null; // 或返回一个加载中的组件等待重定向 } return <Route {...rest} element={<Element />} />; } // 在路由配置中使用路由守卫 function App() { return ( <Routes> <Route path="/" element={<HomePage />} /> <PrivateRoute path="/dashboard" element={<DashboardPage />} /> <Route path="/login" element={<LoginPage />} /> </Routes> ); } ``` 在上面的示例中,我们创建了一个 `PrivateRoute` 组件作为路由守卫,通过判断用户是否已登录来决定是否允许访问受保护的页面。如果用户未登录,则使用 `useNavigate` 钩子函数进行重定向到登录页。 在 `<Routes>` 组件中,我们使用 `<Route>` 定义了几个路由规则,其中包括一个受保护的路由 `/dashboard`,它使用了我们自定义的 `PrivateRoute` 组件来进行路由守卫。 请注意,这只是一个简单示例,实际项目中可能需要更复杂的路由守卫逻辑。你可以根据具体需求来自定义和扩展路由守卫功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值