React 对比 Vue 如何做路由鉴权? react路由鉴权和路由守卫
ztj100 2024-12-22 22:01 31 浏览 0 评论
前言
学过 Vue 的小伙伴肯定知道,在 Vue 中,路由守卫可以帮助我们一站式进行路由鉴权。我们只需要在全局前置路由守卫 (beforeEach) 钩子函数中判断逻辑即可,方便快捷。
但是在 React 中,如何实现类似的功能呢?本文将对比 Vue 和 React 路由鉴权的方式,带你了解如何在 React 中配置路由并实现路由鉴权。
在Vue中如何实现
以 Vue3 为例
配置路由
这里我们简单配置了三个路由,首页、关于和登录页面,除了登录页外都需要登录。
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
import Login from '@/views/Login.vue';
const routes = [
{
path: '/',
name: 'Home',
meta: {
title: '首页',
needLogin: true,
},
component: Home,
},
{
path: '/about',
name: 'About',
meta: {
title: '关于',
needLogin: true,
},
component: About,
},
{
path: '/login',
name: 'Login',
meta: {
title: '登录',
},
component: Login,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
这里我们在路由中添加了一个meta属性,它一般用来存储路由的元信息,什么意思,就是我们可以通过这个对象来判断某个路由是否需要登录权限、页面标题、特定布局等等信息。
这里我们设置 meta.needLogin 来标识某个路由是否需要登录权限,通过 meta.title 来设置页面标题,然后在路由守卫中动态更改 document.title即可。
路由守卫
为什么路由守卫能做?
路由守卫是 Vue Router 中用于控制路由导航行为的功能。它允许在用户从一个路由导航到另一个路由之前、期间或之后执行自定义逻辑。
而全局前置路由守卫是在每次路由导航开始前都会被调用。
这样我们只需在路由跳转前,即全局前置路由守卫中去判断要去的路由是否需要登陆,并且判断用户是否登录即可!!
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('my-token'); //用户登陆自动生成的token
if (to.meta.title) {
document.title = to.meta.title; //设置路由标题
}
if (to.meta.needLogin && !token) { // 如果需要登录但是未登录,跳转到登录页面
next('/login');
} else { //否则放行
next();
}
});
app.use(router).mount('#app');
在 Vue 中,实现路由拦截鉴权的核心是使用 Vue Router 提供的 beforeEach 全局前置守卫。在这个守卫函数中,我们可以根据路由的 meta.needLogin 属性,判断是否需要进行登录验证。如果用户未登录且访问了需要登录的页面,则重定向至登录页。
在React中怎么实现
Vue 中很容易实现,问题来了,React 中怎么做?
这里,我们使用 React Router 6的最新的路由配置写法,跟 Vue 简直不要太像
配置路由
首先第一步同样是配置路由
// router/index.js
import { createBrowserRouter } from 'react-router-dom';
import Layout from '@/components/Layout';
import Home from '@/pages/Home';
import About from '@/pages/About';
import Login from '@/pages/Login';
export const routes = [
{
path: 'home',
index: true,
meta: {
title: '首页',
needLogin: true,
},
element: <Home />,
},
{
path: 'about',
meta: {
title: '关于',
needLogin: true,
},
element: <About />,
},
{
path: '/login',
element: <Login />,
},
];
const router = createBrowserRouter(routes);
export default router;
这里路由对象写法跟 Vue Router 不能说很像,只能说一模一样了,道理都一样,设置meta属性,将需要登录的路由,设置needLogin为true。
1. 组件内部直接判断
跟 Vue 的区别来了,React 可没有路由守卫这一说法,但是道理都一样,我们只需在路由跳转页面展示前一刻判断是否需要登录以及用户是否登录。
但是React怎么实现在跳转前判断逻辑呢?
第一种方法,也是最好想的方法,直接在组件内部的 useEffect 钩子中进行判断,条件不满足重定向去登录即可。
我们知道useEffect在函数组件中充当特定的生命周期,就能在组件渲染前进行逻辑判断
以 Home 页面为例
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
const Home = () => {
const navigate = useNavigate();
const token = localStorage.getItem('my-token');
useEffect(() => {
if (!token) {
navigate('/login');
}
}, [navigate, token]);
return <div>Home Page</div>;
};
export default Home;
这里我们使用useEffect钩子,当页面初次加载或依赖项更新的时候就会重新执行,能够达到我们目的。
我们直接在组件加载前判断用户是否登录,哪里需要登录就在哪里判断,甚至省去了路由配置中的meta属性。
??但是这种方法太笨了,每个需要登录的页面都需要单独写一套这样的代码,很明显可以复用。于是便有了下面这个方法。
2. 高阶组件
高阶组件本质上是一个函数,它接受一个组件作为输入,然后返回一个新的组件。我们可以在这个新组件渲染之前,即在父组件中操作,进行鉴权逻辑判断以实现类似 Vue 前置路由守卫的功能。
// router/Auth.jsx
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { routes, RouterWithTabAuthObject } from './';
// 获取当前路由的元数据
const getRouteMeta = (path, routes) => {
for (const route of routes) {
if (route.path === path) return route;
if (route.children) {
const childRoute = getRouteMeta(path, route.children);
if (childRoute) return childRoute;
}
}
return undefined;
};
const Auth = (props) => {
const location = useLocation();
const token = localStorage.getItem('my-token');
const currentRoute = getRouteMeta(location.pathname, routes);
// 设置页面标题
if (currentRoute?.meta?.title) {
document.title = currentRoute.meta.title;
}
// 如果需要登录但没有 token,重定向到登录页
if (currentRoute?.meta?.needLogin && !token) {
return <Navigate to="/login" replace />;
}
return <>{props.children}</>;
};
export default Auth;
这里逻辑其实跟前置路由守卫是一致,只不过Vue帮你做了封装,显得代码没有那么多,比较简单。
我们来归纳一下,beforeEach可以直接通过to.meta直接拿到元数据,但是 React 需要判断当前loaction和routes路由对象进行查找才能找到对应的路由对象,即此处的getRouteMeta方法,如果有children还需要递归查找,其实 Vue 底层也是这样实现的。
然后通过条件判断和重定向实现鉴权,最后如果不需要重定向,正常渲染 props.children,即子组件。
全局注册
Auth组件已经完成,还需要做一步操作,我们需要用这个高阶将所有路由包裹起来,才能发挥作用。
import { Layout } from 'antd';
import { Outlet } from 'react-router-dom';
import Aside from '@/components/Aside';
import Header from '@/components/Header';
import Auth from '@/router/Auth';
const View = () => {
return (
<Auth>
<Layout>
<Aside />
<Header />
<Content>
<Outlet />
</Content>
</Layout>
</Auth>
);
};
export default View;
这里我一般习惯于将Auth包裹<Layout>组件,如果你没用到Layout,包裹App也是可以的。
总结
- 在Vue中,实现路由拦截鉴权的核心就是使用 beforeEach 全局前置守卫。
- 在React中,暂且不考虑第一种组件内部判断的话,实现路由拦截鉴权就是将每个路由组件使用高阶组件进行包裹,在这个高阶组件里面进行权限相关逻辑的判断。
总而言之,其实不管是 Vue 还是 React 两者的核心思想相同,都是在用户访问受保护页面前,检查其登录状态,并根据检查结果决定是否允许访问,如何找到这的时间点才是关键!
相关推荐
- Linux集群自动化监控系统Zabbix集群搭建到实战
-
自动化监控系统...
- systemd是什么如何使用_systemd/system
-
systemd是什么如何使用简介Systemd是一个在现代Linux发行版中广泛使用的系统和服务管理器。它负责启动系统并管理系统中运行的服务和进程。使用管理服务systemd可以用来启动、停止、...
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
-
Linux系统日常巡检脚本,巡检内容包含了,磁盘,...
- 7,MySQL管理员用户管理_mysql 管理员用户
-
一、首次设置密码1.初始化时设置(推荐)mysqld--initialize--user=mysql--datadir=/data/3306/data--basedir=/usr/local...
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
-
1.1数据库的核心概念在开始Python数据库编程之前,我们需要先理解几个核心概念。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它就像一个电子化的文件柜,能让我们高效...
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
-
设置WGCloud开机自动启动服务init.d目录下新建脚本在/etc/rc.d/init.d新建启动脚本wgcloudstart.sh,内容如下...
- linux系统启动流程和服务管理,带你进去系统的世界
-
Linux启动流程Rhel6启动过程:开机自检bios-->MBR引导-->GRUB菜单-->加载内核-->init进程初始化Rhel7启动过程:开机自检BIOS-->M...
- CentOS7系统如何修改主机名_centos更改主机名称
-
请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1.前言本文将讲解CentOS7系统如何修改主机名。...
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
-
在Linux服务器管理中,SSH(SecureShell)是远程操作的核心工具。以下是SSH终端操作的常用命令和技巧,涵盖连接、文件操作、系统管理等场景:一、SSH连接服务器1.基本连接...
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
-
为什么需要配置开机自启?想象一下:电商服务器重启后,MySQL和Nginx没自动启动,整个网站瘫痪!这就是为什么开机自启是Linux运维的必备技能。自启服务能确保核心程序在系统启动时自动运行,避免人工...
- Kubernetes 高可用(HA)集群部署指南
-
Kubernetes高可用(HA)集群部署指南本指南涵盖从概念理解、架构选择,到kubeadm高可用部署、生产优化、监控备份和运维的全流程,适用于希望搭建稳定、生产级Kubernetes集群...
- Linux项目开发,你必须了解Systemd服务!
-
1.Systemd简介...
- Linux系统systemd服务管理工具使用技巧
-
简介:在Linux系统里,systemd就像是所有进程的“源头”,它可是系统中PID值为1的进程哟。systemd其实是一堆工具的组合,它的作用可不止是启动操作系统这么简单,像后台服务...
- Linux下NetworkManager和network的和平共处
-
简介我们在使用CentoOS系统时偶尔会遇到配置都正确但network启动不了的问题,这问题经常是由NetworkManager引起的,关闭NetworkManage并取消开机启动network就能正...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
pytorch中的 scatter_()函数使用和详解
-
与 Java 17 相比,Java 21 究竟有多快?
-
基于TensorRT_LLM的大模型推理加速与OpenAI兼容服务优化
-
这一次,彻底搞懂Java并发包中的Atomic原子类
-
- 最近发表
-
- Linux集群自动化监控系统Zabbix集群搭建到实战
- systemd是什么如何使用_systemd/system
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
- 7,MySQL管理员用户管理_mysql 管理员用户
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
- linux系统启动流程和服务管理,带你进去系统的世界
- CentOS7系统如何修改主机名_centos更改主机名称
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)