Vue根据用户权限动态更新路由规则(附上案例及思路)

在之前完成的Vue项目中,用到了动态路由。总结了一下特发这篇文章整理思路

Vue项目实现动态更新路由的方式大致分为两种:

  1. 前端定义好路由,登录时根据用户的权限来动态更改路由 (前端处理路由)
  2. 登录后获取后台返回用户对应权限的路由集合,调用接口拿到后处理 (后端处理路由)

此文章分享的是第一种类型。

先说一下使用场景和思路:
例如一个管理系统,需要根据用户登录返回的权限等级然后动态的更改routes中的路由对象,根据用户的权限让用户看到该看到的页面。

用到的技术:
VuexRouterlocalStorage,和一些关键函数(pushaddRoutes

这只是一个小案例,所以只是模拟的后台数据,数据如下:
src/data/data.js

export const loginByUserInfo=[
    {id:1,"username":"admin",pawssord:"1234","role":"A"},
    {id:2,"username":"xiaohong",pawssord:"1234","role":"B"},
    {id:3,"username":"xiaoming",pawssord:"1234","role":"C"}
]

字段role为该用户的权限等级(分为三个权限A、B、C)

现在数据有了,那么就可以实现用户登录了。

Login.vue

export default {
  data() {
    return {
      loginForm: {
        username: "admin",
        password: "1234",
      },
    };
  },
  methods: {
    login() {                     //点击登录执行此方法
      this.$store
        .dispatch("index/userLongin", this.loginForm)           //调用Vuex中actions中userLongin方法验证
        .then((res) => {
          if (res) {
            console.log("登录成功!");
            this.$router.push({ path: "/" });               
          }
        })
        .catch((error) => {
          if (!error) {
            console.log("登录失败!");
          }
        });
    },
  },
};

template中的代码块就不贴上来了(太简单了)
当用户点击登录按钮,调用Vuex中定义的验证方法,返回一个Promise对象,验证是否登陆成功。

src/store/login

import { loginByUserInfo } from "../../data/data"             //获取data数据

const state = {
    username: "",           //用户名
    role: "",              //登录用户的权限
    newrouter: []          //过滤好的路由规则
}
const mutations = {
    // 保存用户名到vuex
    SET_USERNAME(state, username) {
        state.username = username
    },
    // 保存权限到vuex
    SET_ROLE(state, role) {
        state.role = role;
    },
    // 保存路由规则vuex
    SET_NEWROUTER(state, newrouter) {
        state.newrouter = newrouter;
    }
}

const actions = {
    // info:传过来的账号和密码
    userLongin({ commit }, info) {       //验证是否登录成功
        console.log(info); 
        var data = null;
        var count = 0;
        for (let index = 0; index < loginByUserInfo.length; index++) {
            if (info.username == loginByUserInfo[index].username && info.password == loginByUserInfo[index].pawssord) {       // 验证登录是否成功
                return new Promise((resolve) => {
                    commit("SET_USERNAME", loginByUserInfo[index].username);                 // 保存用户名到Vuex
                    commit("SET_ROLE", loginByUserInfo[index].role);                         // 保存权限到vuex
                    localStorage.setItem("username", loginByUserInfo[index].username);       // 保存用户名到本地
                    localStorage.setItem("role", loginByUserInfo[index].role);               // 保存权限到本地
                    data = { username: loginByUserInfo[index].username, role: loginByUserInfo[index].role }         // 返回用户名和权限
                    resolve(data);
                })
            }
            if (info.username != loginByUserInfo[index].username || info.password != loginByUserInfo[index].pawssord) {      
                count++;
            }
        }
        if (count == loginByUserInfo.length) {                     //验证登录失败
            return new Promise((resolve,reject) => {
                reject(data)
            })
        }
    },
    roles({ commit }, newrouter) {                    //最后把过滤的路由存储路由到Vuex中
        console.log(newrouter);
        return new Promise((resolve, reject) => {
            commit("SET_NEWROUTER", newrouter);
            localStorage.getItem("quanxiang", newrouter);
            resolve(newrouter);
        })
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions,
}

state中定义好变量接收用户登录成功后接收用户名、用户权限。newrouter在这个时候还没有赋值,是在用户登录成功后页面跳转触发router.beforeEach()全局路由导航守卫时,使用一些判断和filter过滤后再赋值,你可以仔细看最上面Login.vue中的代码。(登录成功页面会跳转触发router.beforeEach()全局路由导航)

src/store/store.js

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex);


import index from "./login/index.js"

// import getters from "./getters"

export const store=new Vuex.Store({
    modules:{
        index,
    },
    getters:{
        username:state=>state.index.username,
        role:state=>state.index.role,    
        newrouter:state=>state.index.newrouter
    }
})

这里使用了vuex中的modules概念,src/store/login/index.js只是一个‘小仓库’会被外面的‘大仓库’src/store/store.js集中管理。
src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const Login=()=>import("@/components/Login")
const Blue=()=>import("@/components/pages_child/Blue")
const Main=()=>import("@/components/Main")
const Red=()=>import("@/components/pages_child/Red")
const Yellow=()=>import("@/components/pages_child/Yellow")

//不管什么权限,都可以访问的登录路由
export default new Router({
  mode:"history",
  routes: [
    {
      // 登录路由规则
      path: '/login',
      component: Login,
    }]
})

// 定义动态路由规则
export const pwerRouter=[{
  // 跟组件
  path:"/",component:Main,redirect:"/red",hidden:false,
  children:[
    // 跟组件下面的子组件   可修改
    {path:"/red",name:"red",component:Red},
    {path:"/Yellow",name:"Yellow",component:Yellow,meta:{role:"B"}},
    {path:"/Blue",name:"Blue",component:Blue,meta:{role:"C"}},
  ]
}]

src/router/index.js中定义好路由规则并返回,pwerRouter则是需要过滤的路由集合。
那么就要对pwerRouter进行过滤了(关键代码来了)

main.js 核心代码

import Vue from 'vue'
import App from './App'

// 引用自定义动态路由
import {pwerRouter} from './router/index'
// 引用登录路由
import router from "./router/index"
// 引用vuex   包含了小仓库
import {store} from "./store/store.js"       

// 定义全局导航守卫    根据权限用来动态的改变路由规则
router.beforeEach((to,from,next)=>{
  // 每次跳转都会进入这个方法验证
  // 判断是否有权限
  if(store.getters.role){          //拿到用户权限进行判断              
       // 已经存储路由规则到vuex中,就响应的跳转(该去哪就去哪)
      if(store.getters.newrouter.length!=0){
          next();
      }else{                    //进行判断和过滤
        let newrouter;
        //这里的根据项目页面的权限进行判断和过滤
        //因为我的小案例是规定A权限的用户可以看到所有页面
        if(store.getters.role=="A"){
          newrouter=pwerRouter;
        }
        // 否则就是要过滤路由规则的
        else{
            let newchild=pwerRouter[0].children.filter(myroute=>{
              // 根据filter方法判断留下还是删除该路由
              if(myroute.meta){
                // 如果用户拥有该选取,并且该权限可以看到这个路由,则留下该路由,否则删除
                if(myroute.meta.role==store.getters.role){
                    return true;
                }
                return false;
              }
              else{
                return true;
              }
            })
            console.log(newchild);
            newrouter=pwerRouter;
            // 接收删除后的路由规则
            pwerRouter[0].children=newchild;
        }
        router.addRoutes(newrouter);    //拼接路由到Routers
        // 最后把路由存储到vuex中
        store.dispatch("index/roles",newrouter).then(res=>{
          // 跳转到对应的路由
          next({...to});
        })
      }
  }
  // 没有权限  就先登录
  else{
    if(["/login"].indexOf(to.path)!=-1){        //如果在登录页跳转登录页
      next();                                   //还是跳转到登录页
    }else{
      next("/login");
    }
  }
})

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

当用户登录成功后触发页面跳转,会触发router.beforeEach()路由守卫进行判断和filter过滤。
具体怎么判断就需要根据项目权限需要进行判断了,因为这只是个小案例 (只模拟了3个权限级别,A权限可以访问所有页面,B权限可以访问Red、Yellow页面,C权限可以看到Red、Blue页面),所以判断就比较简单,也比较随意。

router.addRoutes(newrouter); 方法把进行过滤的路由追加到Router对象中。
再调用actions中定义的roles方法,把过滤的路由存储到Vuex中,并且跳转到对应的页面中。

到这里已经完成了根据用户的权限进行判断,并且已经存储到Router对象中和Vuex中
接下来就是把Vuex中的路由渲染到页面,用户点击跳转到对应的页面
src/components/Main.vue

<template>
  <div id="mainbox">
    <router-link
      id="div"
      v-for="imter in newrouter[0].children"
      :to="imter.path"
      :key="imter.id"
    >
      {{ imter.name }}
    </router-link>
    <br /><br />
    <button v-on:click="stop">退出登录</button>
	<br/><br/>
	<router-view></router-view>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  created() {},
  computed: {
    newrouter() {
      // 监听Vuex中的路由变化就返回当中的路由渲染到页面
      return this.$store.getters.newrouter;
    },
  },
  methods: {
    stop() {
      this.$router.go(0);
    },
  },
};
</script>

思路简单易懂,希望对大家有帮助。

最后附上效果图
效果图

大功告成了
  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值