React路由守卫实现:基于高阶组件的路由拦截方案

作者:小积木时间:2026-10-24 13:59:27浏览:215

本文详解React中实现路由守卫的方法。针对React Router 4.0+取消onEnter钩子的情况,介绍通过定义routerMap配置auth字段,并利用FrontendAuth高阶组件拦截Route渲染逻辑。结合localStorage判断登录状态,实现未登录跳转登录页、已登录跳转主页的完整拦截流程。

React路由守卫实现原理

与Vue框架提供内置的路由守卫不同,React实现路由拦截通常需要在路由配置中定义元数据(meta)。Vue中的beforeEnter等钩子函数用于在进入路由前进行校验,若校验失败则跳转至404或登录页;而在React中,这种机制需要开发者自行构建。


...
router.beforeEach(async(to, from, next) => {
    const toPath = to.path;
    const fromPath = from.path;
})
...

基于render属性的拦截思路

React实现路由拦截的核心思路是利用Route组件的render属性。通过判断特定的拦截条件,动态渲染不同的组件以实现跳转控制。在React Router 4.0之前,框架曾提供onEnter钩子,但4.0版本后改为声明式组件写法(路由即组件),因此原生的路由守卫功能被移除,需要手动实现。


import * as React from 'react';
import { HashRouter,Switch,Route,Redirect } from 'react-router-dom';
 
import Index from "./page/index";
import Home from "./page/home";
import ErrorPage from "./page/error";
import Login from "./page/login";
 
export const Router = () => (
    <HashRouter>
        <Switch>
            <Route path="/" exact component={Index}/>
            <Route path="/login" exact component={Login}/>
            <Route path="/home" exact component={Home}/>
            <Route path="/404" exact component={ErrorPage}/>
            <Redirect to="/404" />
        </Switch>
    </HashRouter>
);

若不使用路由拦截,基础的Router组件结构如下所示:

上述Router组件涵盖了三个主要页面视图: 登录页 主页 404错误页 同时配置了四条路由规则: 根路径路由 登录路径路由 主页路径路由 404路径路由 其中,根路径和/home路径均指向主页组件。这是一个基础的路由配置,允许在登录、主页和404页面间自由切换,但存在安全漏洞: 用户未登录时可直接访问主页 用户已登录时仍可通过输入/login路径强制跳转至登录页 我们需要实现如下功能: 当用户未登录时,禁止直接访问主页,若尝试访问则重定向至登录路由 当用户已登录时,禁止再次访问登录页,若尝试访问则重定向至主页 实现该功能主要有两种方案: 在各组件内部通过props中的history对象手动判断跳转 采用全局路由守卫机制统一处理

路由配置与高阶组件实现

首先在src根目录下创建routerMap.js文件,代码示例如下:


/**
 * 定义路由组件,将 auth 设置为 true,表示该路由需要权限校验
 */

import Admin from "./pages/Admin";
import Login from "./pages/Login";
import Error from "./pages/Error";

export const routerMap = [
    {path: "/", name: "admin", component: Admin, auth: true},
    {path: "/login", name: "Login", component: Login},
    {path: "/error", name: "error", component: Error},
];

所有路由的渲染逻辑均交由FrontendAuth高阶组件代理执行。该组件的具体实现代码如下:


/**
 * 路由守卫校验
 */
import React, {Component} from "react";
import {Route, Redirect} from "react-router-dom";

class FrontendAuth extends Component {
    // eslint-disable-next-line no-useless-constructor
    constructor(props) {
        super(props);
    }

    render() {
        const {routerConfig, location} = this.props;
        const {pathname} = location;
        const isLogin = localStorage.getItem("user");
        console.log(pathname, isLogin);
        console.log(location);
        // 如果该路由不用进行权限校验,登录状态下登陆页除外
        // 因为登陆后,无法跳转到登陆页
        // 这部分代码,是为了在非登陆状态下,访问不需要权限校验的路由
        const targetRouterConfig = routerConfig.find(
            (item) => item.path === pathname
        );
        console.log(targetRouterConfig);
        if (targetRouterConfig && !targetRouterConfig.auth && !isLogin) {
            const {component} = targetRouterConfig;
            return <Route exact path={pathname} component={component}/>;
        }
        if (isLogin) {
            // 如果是登陆状态,想要跳转到登陆,重定向到主页
            if (pathname === "/login") {
                return <Redirect to="/"/>;
            } else {
                // 如果路由合法,就跳转到相应的路由
                if (targetRouterConfig) {
                    return (
                        <Route path={pathname} component={targetRouterConfig.component}/>
                    );
                } else {
                    // 如果路由不合法,重定向到 404 页面
                    return <Redirect to="/error"/>;
                }
            }
        } else {
            // 非登陆状态下,当路由合法时且需要权限校验时,跳转到登陆页面,要求登陆
            if (targetRouterConfig && targetRouterConfig.auth) {
                return <Redirect to="/login"/>;
            } else {
                // 非登陆状态下,路由不合法时,重定向至 404
                return <Redirect to="/error"/>;
            }
        }
    }
}

export default FrontendAuth;

接着,在App.js中定义Router组件,该组件是经过FrontendAuth高阶组件包装后的最终结果:


import './App.less';
import React, {Fragment} from "react";
import {Switch} from 'react-router-dom'
import FrontendAuth from "./FrontendAuth";
import {routerMap} from "./routerMap";

function App() {
    return (
        <Fragment>
            {/*只匹配一个,匹配成功就不往下匹配,效率高*/}
            <Switch>
                <FrontendAuth routerConfig={routerMap}/>
            </Switch>
        </Fragment>
    );
}

export default App;

测试验证

React路由守卫实现原理

至此,关于React路由守卫(路由拦截)的实现方案介绍完毕。如需了解更多React路由相关内容,可查阅本站过往文章或继续浏览后续教程,感谢支持。

作者最新文章
相关文章
更多