1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue-router的addRoute方法实现权限控制

vue-router的addRoute方法实现权限控制

时间:2023-05-10 06:48:31

相关推荐

vue-router的addRoute方法实现权限控制

在项目实践中,往往需要用户登录后由后端返回用户的权限,来动态配置路由,vue-router提供了两个方法router.addRoutes(),router.addRoute()可以进行动态路由配置,这里需要注意的是vue-router的options属性存放的是路由配置的信息,并不是响应式的,在动态添加路由规则后,router.options.routes属性不会改变,如果需要更新router.options.routes,则需要手动更改。

下面的代码基于vue-router版本:3.5.1,版本的变化可能会存在一些不同,如使用已废弃的router.addRoutes方法会出现警告。

参考:/zh/api/#router-addroutes

router.addRoutes 和router.addRoute 新路由规则

router.addRoutes 添加多条新路由规则

router.addRoutes(routes: Array<RouteConfig>)

动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组

router.addRoute 添加一条新路由规则

如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。

addRoute(route: RouteConfig): () => void

addRoute方法可用于为现有路由添加子路由规则

addRoute(parentName: string, route: RouteConfig): () => void

在项目实践时,通常在用户登录后获取到用户的权限表,可以将这些数据保存到前端。

下面是一个简单的例子,忽略了很多细节,旨在演示通过路由进行权限控制的方法。

router.beforeEach()中进行全局前置守卫如果路由地址在白名单中则放行(例外:如果路由是登录并且存在token,重定向到首页) 不在白名单,且无token,重定向到登录页 不在白名单,且有token,放行

在登录时用setTimeout方法模拟异步获取动态路由和token,并保存到localStorage中,调用generateRoutes方法添加路由规则。

在页面手动刷新时,配置的动态路由会消失需要在router.onReady()方法中,再次调用generateRoutes方法。

generateRoutes方法遍历动态路由数组,将成员转为RouteConfig,并调用addRoute方法。

用vue cli搭建了这样一个组件结构

模板具体什么样式无所谓,这里只做动态路由的展示

router/index.js

import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/Home.vue'import Layout from '../views/Layout.vue'import {generateRoutes } from '../utils'Vue.use(VueRouter)const constantRoutes = [{path: '/',name: 'Home',component: Layout,redirect: '/index',children: [{path: 'index',component: Home},{path: 'about',name: 'About',component: () => import('../views/About.vue')}]},{path: '/login',name: 'login',component: () => import('../views/Login.vue')},{path: '/404',component: () => import('../views/404Error.vue')}]const createRouter = () => new VueRouter({mode: 'history',routes: constantRoutes})const router = createRouter()// 检查是否存在于免登陆白名单function inWhiteList (toPath) {const whiteList = ['/login', '/404']const path = whiteList.find((value) => {// 使用正则匹配const reg = new RegExp('^' + value)return reg.test(toPath)})return !!path}router.beforeEach((to, from, next) => {console.group('%c%s', 'color:blue', `${new Date().getTime()} ${to.path} 的全局前置守卫----------`)console.log('所有活跃的路由记录列表', router.getRoutes())console.groupEnd()const token = localStorage.getItem('token')// 检查to.path是否存在于免登陆白名单if (inWhiteList(to.path)) {if (to.path === '/login' && token) {// 避免重复登录next({path: '/' })} else {next()}return false}// 判断是否已经登录,未登录则重定向到登录页(通过query传参记录原来的路径)if (!token) {const toPath = to.fullPath !== '/login' ? to.fullPath : '/'next({path: '/login',query: {redirect: toPath }})} else {next()}})// 在路由完成初始导航时调用,如果有异步操作放置到这里router.onReady(() => {console.group('%c%s', 'color:red', `${new Date().getTime()} 路由完成初始导航----------`)console.log('添加前-所有活跃的路由记录列表', router.getRoutes())generateRoutes()console.log('添加后-所有活跃的路由记录列表', router.getRoutes())console.groupEnd()})// 重置路由export function resetRouter () {const newRouter = createRouter()router.matcher = newRouter.matcher}export default router

Login.vue

<template><div><button @click="signIn">登录</button></div></template><script>import {generateRoutes } from '../utils'export default {methods: {signIn () {const routes = [{id: 1,parentId: 0,path: '/sys',component: 'Layout.vue',redirect: '/sys/user'},{id: 2,parentId: 1,path: 'user',component: 'User.vue'}]setTimeout(() => {localStorage.setItem('token', '123456')localStorage.setItem('routes', JSON.stringify(routes))console.log('登录成功')generateRoutes()this.$router.push(this.$route.query.redirect || '/')}, 1000)}}}</script>

Layout.vue

<template><div class="layout"><div class="header"><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link> |<router-link to="/sys">Sys</router-link> |<router-link to="/sys/user">User</router-link><button @click="signOut">登出</button></div><router-view/></div></template><script>import {resetRouter } from '../router/index'export default {methods: {signOut () {localStorage.removeItem('token')localStorage.removeItem('routes')resetRouter()console.log('登出后的路由', this.$router.getRoutes())this.$router.push('/login')}}}</script>

generateRoutes()

export function generateRoutes () {const _asyncRoutes = JSON.parse(localStorage.getItem('routes'))const routes = _asyncRoutes.map(({id, parentId, path, component, redirect }) => {const route = {id, parentId, path, redirect }ponent = (resolve) => require([`../views/${component}`], resolve)return route})const asyncRoutes = toTree(routes)asyncRoutes.forEach(route => {router.addRoute(route)})router.addRoute({path: '*',redirect: '/404'})}

这个有个toTree()用于将数组转成tree,来实现路由嵌套

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。