前端框架对比系列之vue和react的登录路由守卫鉴权

前言

前端路由守卫鉴权涉及的内容很多。本文主要介绍的是vuereact框架的 登录路由守卫鉴权过程,即登录之后才能进入系统的某些页面,没登录成功话需要重定向到登录页,这种形式的拦截鉴权基本上每个系统都会有这样的需求。

1. react-router-dom 5.x.x 的路由守卫鉴权

对于react框架,我们常用的路由插件 React-Router-dom,话不多说,基于已有的基础初始化项目工程,我们展开讨论。

1.1 定义 routes

基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js,在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。

js 复制代码
import Home from "../pages/Home";
import About from "../pages/About";
import Login from "../pages/Login";

const routes = [
  {
    path: "/home",
    component: Home,
    meta: {
      title: "首页",
      needLogin: false, // 不需要登录就可以打开页面
    },
  },
  {
    path: "/about",
    component: About,
    meta: {
      title: "关于",
      needLogin: true, // 需要登录后菜可以打开页面
    },
  },
  {
    path: "/login",
    component: Login,
    meta: {
      title: "登录",
      needLogin: false, // 不需要登录就可以打开页面
    },
  },
  {
    path: '/',
    redirect: '/home'
  },
];

export default routes;

1.2 定义一个路由组件 auth.js

在文件目录 router中新建一个路由组件 auth.js, 该组件的作用是实现路由的拦截逻辑:

js 复制代码
import { Route, Redirect } from "react-router-dom";
function Auth(props) {
  const {
    component: Component,
    path,
    meta,
    routes,
    redirect,
    exact,
    strict,
  } = props;

  // 设置网页标题
  if (meta && meta.title) {
    document.title = meta.title;
  }

  // 重定向
  if (redirect) {
    return <Redirect to={redirect} />;
  }

  // 判断是否需要登录
  if (meta && meta.needLogin) {
    const token = localStorage.getItem("react-demo-token");
    // 没登录去登录页
    if (!token) {
      return <Redirect to="/login" />;
    }
  }

  return (
    <Route
      path={path}
      exact={exact}
      strict={strict}
      render={(props) => <Component {...props} routes={routes} />}
    ></Route>
  );
}

export default Auth;

1.3 在根组件根据routes配置来渲染Auth组件

如下图所示,对于前端单页面应用项目,需要在主页名提供一个渲染区域,该区域通过不同的url路径,映射生成不同的页面,即我们所说的路由渲染过程:

js 复制代码
/* eslint-disable no-unused-vars */
import { ConfigProvider } from 'antd';
import routes from "./router/routes";
import { Switch } from "react-router-dom";
import Auth from './router/auth';

function App() {
  return (
    <ConfigProvider theme={{ token: { colorPrimary: '#ff721f' } }}>
      <div className="App">
        <div className='app-tab' style={{ borderBottom: 'solid 1px grey' }}>
          <h1>react 首页导航</h1>
        </div>
        {/* 路由渲染区域 */}
        <Switch>
          {routes.map((route) => {
            return (
              // 路由鉴权
              <Auth key={route.path} {...route}></Auth>
            );
          })}
        </Switch>
      </div>
    </ConfigProvider>
  );
}

export default App;

必须在入口文件index.js中使用 BrowserRouter 组件:

js 复制代码
import { BrowserRouter } from "react-router-dom";

ReactDOM.createRoot(document.getElementById("root")).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

2. vue-router 3.x.x 的路由守卫鉴权

vue2 中使用的路由主要是vue-router 3.x.x,该路由插件内置了七个路由守卫,对于路由拦截相关需求,基本上不需要我们额外开发,但是在实际开发过程中,对于前端鉴权这块,我们基本上使用 beforeEach 全局前置守卫就能满足基本需求开发。

2.1 定义 routes

首先我们定义好系统的路由,对于非首页组件可以使用路由懒加载。在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js

js 复制代码
import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页"
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于"
    }
  }
];

export default routes;

2.2 实例化 router,并定义路由守卫逻辑

创建好路由后就定义路由拦截的逻辑了。主要通过 beforeEach 全局前置守卫。这里的核心逻辑就是判断前往的页面是否需要登录,需要登录就进一步判断当前系统是否有token,有就进入页面,没有就重定向到登录页。

js 复制代码
import VueRouter from "vue-router";
import routes from "./routes"
import Vue from 'vue';

Vue.use(VueRouter);

const router = new VueRouter({
  mode: "hash",
  routes,
});

router.beforeEach((to, from, next) => {
  // 判断是否需要登陆
  if (to.meta.needLogin) {
    const token = localStorage.getItem("vue2-demo-token");
    if (token) {
      next();
    } else {
      next("/login");
    }
  } else {
    // 不需要登录则直接放行
    next();
  }
});

// 全局后置守卫可以修改标题
router.afterEach((to, from) => {
  if (to.meta.title) {
    document.title = to.meta.title;
  }
});

export default router;

2.3 配置路由的入口

在首页 App.vue中添加标签 router-view,即路由跳转区域。

js 复制代码
<template>
  <div id="app">
    <div class="app-tab">
      <h3>vue2 首页导航</h3>
    </div>
    <router-view></router-view>
  </div>
</template>

在主文件入口处引用 router 实例:

js 复制代码
import router from './router'

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

3. vue-router 4.x.x 的路由守卫鉴权

vue3 中使用的路由主要是vue-router 4.x.x,该路由插件内置了6个路由守卫,对于路由拦截相关需求,基本上不需要我们额外开发,但是在实际开发过程中,对于前端鉴权这块,我们基本上使用 beforeEach 全局前置守卫就能满足基本需求开发。

js 复制代码
// 全局前置守卫
beforeEach(to, from, next) 
// 全局解析守卫
beforeResolve(to, from, next) 
// 路由守卫
beforeEnter(to, from, next) 
// 组件内守卫(更新)
onBeforeRouteUpdate(to, from, next) 
// 组件内守卫(离开)
onBeforeRouteLeave(to, from, next) 
// 全局后置守卫
afterEach(to, from) 

3.1 定义 routes

首先我们定义好系统的路由,对于非首页组件可以使用路由懒加载。在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js

js 复制代码
import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页"
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于"
    }
  }
];

export default routes;

3.2 实例化 router,并定义路由守卫逻辑

创建好路由后就定义路由拦截的逻辑了。主要通过 beforeEach 全局前置守卫。这里的核心逻辑就是判断前往的页面是否需要登录,需要登录就进一步判断当前系统是否有token,有就进入页面,没有就重定向到登录页。

js 复制代码
import { createRouter, createWebHistory , createWebHashHistory} from "vue-router";
import routes from "./routes"

const router = createRouter({
  history: createWebHashHistory(), // hash 模式
  routes,
});

router.beforeEach((to, from, next) => {
  // 判断是否需要登陆
  if (to.meta.needLogin) {
    const token = localStorage.getItem("vue3-demo-token");
    if (token) {
      next();
    } else {
      next("/login");
    }
  } else {
    // 不需要登录则直接放行
    next();
  }
});

// 全局后置守卫可以修改标题
router.afterEach((to, from) => {
  if (to.meta.title) {
    document.title = to.meta.title;
  }
});

export default router;

3.3 配置路由的入口

在首页 App.vue中添加标签 router-view,即路由跳转区域。

js 复制代码
<template>
  <div id="app">
    <div class="app-tab">
      <h3>vue2 首页导航</h3>
    </div>
    <router-view></router-view>
  </div>
</template>

在主文件入口处引用 router 实例 ( 此处要注意vue3 和 vue2 框架引用的差异 ):

js 复制代码
import router from './router'
import { createApp } from 'vue'

const app = createApp(App);
app.use(router);
app.mount('#app')

总结

  1. React中,实现路由守卫鉴权的核心就是将每个路由组件使用 高阶组件 进行包裹,在这个高阶组件里面进行权限相关逻辑的判断。
  2. Vue 中,实现路由守卫鉴权的核心就是通过使用 vue-router 自身提供的 beforeEach 全局前置守卫。
相关推荐
恋猫de小郭11 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅17 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606118 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了18 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅18 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅18 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅19 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment19 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅19 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊19 小时前
jwt介绍
前端