优秀的编程知识分享平台

网站首页 > 技术文章 正文

Vue与React 登录权限全局拦截对比

nanyue 2025-05-22 12:26:57 技术文章 9 ℃

无论是vue还是react全局登录权限的拦截在业务逻辑上都需要实现两处:

  1. 对调用后台api接口返回结果进行拦截.如果返回401状态,或者特定结果就说需要需要登录.这块代码都相同.
  2. 对路由进行拦截. 这里vue和react实现的方式各有不同.

vue路由如何进行拦截

vue比较简单,直接用全局路由守卫就可以实现.

router.beforeEach((to,from, next) => {
	//判读有没有登录,或者当前页面是不是登录页面,做相应的处理.
  if(store.state.userInfo || to.path === "/login"){
		next()
	} else {
		next({
			path: "/login"
		})
	}
) 

react路由如何进行拦截

1. 高阶组件的编写

import React from 'react'
import { Route, Redirect } from 'react-router-dom'
import { message } from 'antd'
 
export default function AuthRoute({ component: Component, ...rest }) {
    return (
        <Route {...rest} render={(props) => {
            const sid = !!sessionStorage.getItem('sid')
            if (!sid) {
                message.error('请先登录!')
                return (
                    <Redirect to={{
                        pathname: '/',
                        state: {
                            from: props.location
                        }
                    }} />
                )
            } else {
                return <Component {...props} />
            }
        }}></Route>
    )

    
    使用:

import React, { Component } from 'react'
import { Route, Switch, Redirect } from 'react-router-dom'
import AuthRoute from './components/AuthRoute'
import loginfrom './pages/login'
import cloudviewfrom './pages/cloudview'
import Home from './pages/Home'
 
export default class App extends Component {
    render() {
        return (
            <div style = {{height:'100%'}}>
                {/* 一级路由注册 */}
                <Switch>
                    <Route exact path='/' render={() => <Redirect to='/login'/>}></Route>
                    <Route path='/login' component={Login}></Route>
                    <AuthRoute path='/cloudview' component={CloudView}></AuthRoute>
                    <AuthRoute path='/home' component={Home}></AuthRoute>
                </Switch>
            </div>
        )
    }


2.自定义跳转hook,实现路由守卫RouterBeforeEach

官方提供的路由跳转是使用useNavigate hook的,这里我们要实现路由守卫,那么我需要在路由跳转前做逻辑的判断,所以我自定义了一个useUtilsNavigate hook用于跳转前的判断。只要是通过这个hook跳转的路由都可以响应到路由守卫。

import { NavigateFunction, Location, To, NavigateOptions } from "react-router-dom";
import { RouterLoader } from "@/routes/route";
type IrouterBeforeLoad = (to:Ito,location?: Location) => Boolean;
 
interface Ito {
  to: To, options?: NavigateOptions
 }
 
let routerBeforeLoad: IrouterBeforeLoad;
let flag: Boolean = true;
 
const RouterBeforeEach = (fun: IrouterBeforeLoad) => {
  ///页面刷新时,配合loader实现调用,并做拦截重定向,由flag判断是否是初次刷新页面,以免在useUtilsNavigate调用是触发多次路由校验
  RouterLoader((res: any,redirectUrl:string) => { 
    let result: Boolean=true;
    if (flag) { 
      let url = new URL(res.request.url)
      result = fun({ to: url.pathname })
      if (redirectUrl==url.pathname) { 
        result = true;
      }
    }
    return result;
  })
  routerBeforeLoad = fun;
}
 
///所有的js路由跳转通过此函数,由此做路由拦截
const useUtilsNavigate=(navigate:NavigateFunction,location:Location,to: To, options?: NavigateOptions)=>{
  if (routerBeforeLoad && routerBeforeLoad({ to, options }, location)) {
    //flag设置false标志已经不是第一次加载页面
    flag = false;
    navigate(to, options)
  } else {
    return;
  }
  //flag设置false标志已经不是第一次加载页面
  flag = false;
  navigate(to,options)
}
 
export { useUtilsNavigate, RouterBeforeEach };
export type { IrouterBeforeLoad,Ito };

  

RouterLoader这个函数钩子是在路由定义的文件里面导出的,可以看到在route.tsx,其在loader属性里面被调用。loader这个也是新版本提供的一个新功能,其会在组件页面加载时先回调这个钩子,我在这里根据flag判断是否页面初始加载。因为页面通过URL直接打开的话,是没有经过useUtilsNavigate,也就是无法通过它去做路由监听,所以需要使用loader这个钩子,在初次加载时,触发路由守卫。

在程序主入口注册路由守卫钩子

import ReactDOM from 'react-dom';
import {RouterProvider } from "react-router-dom";
import './index.css'
import { Router } from './routes/route';
import { AliveScope } from 'react-activation'
import React from 'react';
import { RouterBeforeEach } from "@/utils/useUtilsNavigate";
RouterBeforeEach(( to,from) => { 
  console.log("路由守卫to", to)
  console.log("路由守卫from", from)
  return true;
})
 
ReactDOM.render(
    <AliveScope>
      <RouterProvider router={Router()}/>
    </AliveScope>,

Tags:

最近发表
标签列表