Vue动态路由addRoutes

本文详细介绍了前端动态路由的两种设置方式:简单角色路由和复杂路由权限设置。简单角色路由通过前端直接配置,而复杂设置则涉及后端返回路由列表供前端渲染。在路由守卫中,通过用户角色过滤并动态添加路由,实现权限控制。登录时将用户角色存储到store中,确保安全访问。
摘要由CSDN通过智能技术生成

动态路由设置一般有两种:

(1)、简单的角色路由设置:比如只涉及到管理员和普通用户的权限。通常直接在前端进行简单的角色权限设置

(2)、复杂的路由权限设置:比如OA系统、多种角色的权限配置。通常需要后端返回路由列表,前端渲染使用

1、简单的角色路由设置

(1)配置项目路由权限

// router.js

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/layout'
Vue.use(Router)
// 权限路由列表
let asyncRoutes = [
    {
        path: '/',
        component: Layout,
        redirect: () => import('@/views/index'),
        redirect: '/home',
        meta: {
           roles:[1,2,3] //三种角色
        },
        children: [
            {
		        path: 'home',
		        component: () => import('@/views/home'),
		        meta: {
		          title: 'tIndex',
		          roles:[1,2,3]
		        }
		      },
           {
        path: 'member',
        component: () => import('@/components/animate'),
        meta: {
          title:'tMember',
          roles:[1,2]
        },
        children:[
          {
            path:'',
            component: () => import('@/views/member'),
            name:'member',
            meta:{
              roles:[1,2]
            },
          },
          {
            path:'detail',
            component: () => import('@/views/member/detail'),
            name:'memberDetail',
            meta:{
              title:'tMemberDetail',
              roles:[1,2]
            }
          },
          {
            path:':scoreId/score',
            component: () => import('@/views/member/score'),
            name:'score',
            meta:{
              title:'tScore',
              roles:[1,2]
            }
          }
        ]
      },
        ]
    },
 
]
// 静态路由
let defaultRouter = [{
  path: '/404',
  name: '404',
  component: () => import('@/views/404/index'),
   meta: {
      title: '404'
  }
},{
  path: '/login',
  name: 'login',
  component: () => import('@/views/login'),
  meta: {
    title:'tLogin'
  },
}]
export const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: defaultRouter
})

2)新建一个公共的asyncRouter.js文件

function hasPermission(roles, route) {
    if (route.meta && route.meta.roles) {
      return roles.some(role => route.meta.roles.includes(role))
    } else {
      return false
    }
  }
  // 递归过滤异步路由表,筛选角色权限路由
  export function filterAsyncRoutes(routes, roles) {
    
    const res = [];
    routes.forEach(route => {
      const tmp = { ...route }
      if (hasPermission(roles, tmp)) {
        if (tmp.children) {
          tmp.children = filterAsyncRoutes(tmp.children, roles)
        }
        res.push(tmp)
      }
    })
  
    return res
  }

(3)创建路由守卫 在main.js当中

// import NProgress from 'nprogress' // 进度条插件
// import 'nprogress/nprogress.css' // 进度条样式
import store from './store'
import storage from '@/utils/storage.js'
import { router, routes } from './router'
import { filterAsyncRoutes } from './router/asyncRouter.js'
const whiteList = ['/login']
router.beforeEach(async(to, from, next) => {
	(to.matched[to.matched.length - 1]?.path === to.matched[to.matched.length - 2]?.path + '/') && to.query ? to.matched[to.matched.length - 2].meta.query = to.query : 0
	// 进度条开始
    // NProgress.start()
     // 获取路由 meta 中的title,并设置给页面标题
    // document.title = to.meta.title
    // 获取用户登录的token
    const hasToken = storage.getLocal('userinfo') && storage.getLocal('userinfo').token
    // 判断当前用户是否登录
    if (hasToken) {
        if (to.path === '/login') {
            next({ path: '/' })
            // NProgress.done()
        } else {
            // 从store中获取用户角色
            const hasRoles = store.state.routes && store.state.routes.length > 0  
            if (hasRoles) {
                next()
            } else {
                try {
                    // 获取用户角色
                    const roles = await store.state.adminUser.auth
                    // 通过用户角色,获取到角色路由表
                    const accessRoutes = filterAsyncRoutes(routes,[roles])
                    // 动态添加路由到router内
                    
                    router.matcher.addRoutes(accessRoutes)
                    store.commit('saveRoute',accessRoutes)
                    next({ ...to, replace: true })
                } catch (error) {
                    // 清除用户登录信息后,回跳到登录页去
                    storage.removeLocal('userinfo')
                    storage.removeLocal('token')
                    store.state.routes = null
                    next(`/login?redirect=${to.path}`)
                    // NProgress.done()
                }
            }
        }
    } else {
        // 用户未登录
        if (whiteList.indexOf(to.path) !== -1) {
            // 需要跳转的路由是否是whiteList中的路由,若是,则直接条状
            next()
        } else {
            // 需要跳转的路由不是whiteList中的路由,直接跳转到登录页
            next(`/login?redirect=${to.path}`)
            // 结束精度条
            // NProgress.done()
        }
    }
})
// router.afterEach(() => {
//     // 结束精度条
//     NProgress.done()
// })

(4)在login登录的时候将roles存储到store中

import storage from '@/utils/storage.js'
const mutations = {
  saveUserInfo (state, data) {
    storage.setLocal('token',data.token)
    storage.setLocal('userinfo', data)
    state.adminUser = data
  },
  saveRoute (state, data) {
    state.routes = data
  },
}
export default mutations

login.vue

import { mapMutations } from "vuex";
export default {
  name: "login",
  data() {
    return {
      ruleForm: {
        username: "",
        password: "",
      },
      rules: {
        username: [
          {
            required: true,
            message: '输入帐号',
            trigger: "blur",
          },
          { min: 3, message: this.$t('min3'), trigger: "blur" },
        ],
        password: [
          {
            required: true,
            message: '输入密码',
            trigger: "blur",
          },
          { min: 6, message: this.$t('min6'), trigger: "blur" },
        ],
      },
    };
  },
  
  methods: {
    ...mapMutations(["saveUserInfo"]),
    async submitAdmin(formName) {
      await this.$refs[formName].validate();
      this.loginHandle(this.ruleForm);
    },
    async loginHandle(ruleForm) {
      let res = await login(ruleForm);
        if (res.code) return;
        this.saveUserInfo(res);
        this.$router.push("/");
        this.$message.success({
          message: this.$t('loginSuccess'),
        });
    },
  },
};

2、复杂的路由权限设置(后端动态返回路由数据)

https://www.jianshu.com/p/4f2566b67989

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值