Vue前端动态路由权限配置

- 在我的使用中,我把动态路由以下分为两种方案。按项目需求选取。

1.半动态配置

:较适合c端,根据用户等级,可体验产品不同功能。

-前端分好权限,把路由配置写死,后端返回该用户的角色之后,前端动态添加该角色有拥有权限的路由即可。(前后端交流较少)

2.纯动态配置

较适合后台管理系统,上级管理员给下级管理赋权各个层级页面。

-所有配置都由后端返回告知,前端动态渲染组件并配置路由。(前后端交流较多,返回的项目文件名称需交流清除)

实现:

- 方案一较为简单,这里只讲述方案二纯动态配置。

0.后端返回的数据

const nav=[{
  path:'/demo1',
  name:'demo1',
  component:'demo1',
  meta:{
    title:'一级路由demo1'
  },
  children:[
    {
      path:'/demo2',
      name:'demo2',
      component:'demo2',
      meta:{
        title:'二级路由demo2'
      },
    }

  ]
},{
  path:'/demo3',
  name:'demo3',
  component:'demo3',
  meta:{
    title:'一级路由demo3'
  },
  children:[
    {
      path:'/demo4',
      name:'demo4',
      component:'demo4',
      meta:{
        title:'一级路由demo4'
      },
    }
  ]
},]

1.Vuex设置缓存

缓存常选用vuex的原因:vuex相较于本地存储具有响应式的作用,vuex不直接暴露出来,安全性高。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    isnav:false, //标记是添加了动态路由
  },
  getters: {
  },
  mutations: {
    setnav(state)
    {
      state.isnav = true
    }
  },
  actions: {
  },
  modules: {
  }
})

2.组件渲染

用element-ui简单渲染出来

Vue前端动态路由权限配置_第1张图片

3.addRoute动态添加路由配置

 addRoutes在新版本已废弃,改用addRoute了

- 这里可以分为两种情况去添加配置,一种是在登录后进入白名单页面后拿到数据,进行动态路由添加。另一种是在访问,白名单页面之外的路由时,拦截下来,并添加路由配置,然后重新跳转页面。两种差异不大。

/*
views 目录结构
├── views                     
│   ├── home
│              └── index.vue   #主页
│   ├── demo1
│              └── index.vue   #一级动态路由页面
│         └── demo2.vue   #二级动态路由页面
│   ├── demo3
│              └── index.vue   #一级动态路由页面
│         └── demo4.vue   #二级动态路由页面
*/

<1>先从简单一级动态路由配置开始

import store from "@/store"
// 定义白名单路由
const routes = [
  {
    path: '/home',
    name: 'home',
    component: ()=>import("@/views/home/index")
  },
  {
    path:'/',
    redirect:"/home" 
  }
]
const arr=["/",'/home']
const router = new VueRouter({
  routes
})
// 将第一次白名单外的请求拦截下来,添加好动态配置,再跳转一次
router.beforeEach(async (to,from,next)=>{
  if(arr.indexOf(to.path)<0)
  {
    if(store.state.isnav){
      next()
    }else{
      const {data:res} = await getuserData()
      const nav=res.nav
      nav.forEach(item=>{
          router.addRoute({
          path:item.path,
          name:item.name,
          meta:item.meta,
          component:()=>import(`@/views/${item.component}`)
          })
      })
      store.commit("setnav") 
   	  next({path:to.path})  //这是不是放行next(),是重新跳转,
    }
  }else{
    // 白名单页面直接放行
    next()
  }
})

这样就实现只有一级路由的动态配置了

<2>多层级动态路由配置

addRoute(parent,nav) 第一个参数传入该路由所添加在的父路由的path。

所以自己封装一个可递归函数,实现多层级动态路由添加,递归出口:不存在children节点。

/*
views 目录结构
├── views                     
│   ├── home
│  			└── index.vue   #主页
│   ├── demo1
│  			└── index.vue   #一级动态路由页面
│     	└── demo2.vue   #二级动态路由页面
│   ├── demo3
│  			└── index.vue   #一级动态路由页面
│     	└── demo4.vue   #二级动态路由页面
*/

import store from "@/store"
// 定义白名单路由
const routes = [
  {
    path: '/home',
    name: 'home',
    component: ()=>import("@/views/home/index")
  },
  {
    path:'/',
    redirect:"/home" 
  }
]
const arr=["/",'/home']
const router = new VueRouter({
  routes
})
// 定义一个可递归的动态添加路由函数
// parent传入上一级路由的路径
async function addRoute(parent,nav)
{
  if(parent)
  {
    // 有父节点则挂载在父节点之下
    nav.forEach(item => {
      router.addRoute(parent,{
        //子路由地址必须加上父路由地址,根据后端数据返回自行决定添加
        path:parent+item.path, 
        name:item.name,
        // 导入路由模块地址,根据自己文件层级关系修改
        component:()=>import("@/views"+parent+"/"+item.component),
      })
      // 若存在子路由,递归添加路由
      if(item.children)
      {
        addRoute(item.path,item.children)
      }
    })
  }else{ 
    // 无父节点,第一个参数为空,全局挂载
    nav.forEach(item => {
      router.addRoute({
        path:item.path,
        name:item.name,
        component:()=>import(`@/views/${item.component}/index`),
      })
      // 若存在子路由
      if(item.children)
      {
        addRoute(item.path,item.children)
      }
    })
  }
}
// 将第一次白名单外的请求拦截下来,添加好动态配置,再跳转一次
router.beforeEach(async (to,from,next)=>{
  if(arr.indexOf(to.path)<0)
  {
    if(store.state.isnav){
      next()
    }else{
      const {data:res} = await getuserData()
      const nav=res.nav
      addRoute(null,nav) //一级动态路由,无父路由传入null
      store.commit("setnav")
   	  next({path:to.path}) 
    }
  }else{
    next()
  }
})
export default router

<3>最后就可以加上白名单、token验证等花里胡哨的东西了。


import store from "@/store"
//设置默认路由
const routes = [
  { path: '/', redirect: '/login' },
  { path: '/login', component: pageLogin},
  { path: '/404', component: page404},
  { path: '*', redirect: '/404' },
];
const router = new  VueRouter(routes)
// 设置默认路由白名单
const login_page=['/404','/login','/']
// 定义一个可递归的动态添加路由函数
// parent传入上一级路由的路径
async function addRoute(parent,nav)
{
  if(parent)
  {
    // 有父节点则挂载在父节点之下
    nav.forEach(item => {
      router.addRoute(parent,{
        //子路由地址必须加上父路由地址,根据后端数据返回自行决定添加
        path:parent+item.path, 
        name:item.name,
        // 导入路由模块地址,根据自己文件层级关系修改
        component:()=>import("@/views"+parent+"/"+item.component),
      })
      // 若存在子路由,递归添加路由
      if(item.children)
      {
        addRoute(item.path,item.children)
      }
    })
  }else{ 
    // 无父节点,第一个参数为空,全局挂载
    nav.forEach(item => {
      router.addRoute({
        path:item.path,
        name:item.name,
        component:()=>import(`@/views/${item.component}/index`),
      })
      // 若存在子路由
      if(item.children)
      {
        addRoute(item.path,item.children)
      }
    })
  }
}
// 通过路由拦截动态添加路由配置
router.beforeEach(async(to,from,next)=>{
  // 判断页面是否为白名单页面并验证token
  if(login_page.indexOf(to.path)<0)
  {
    let accessToken=sessionStorage.getItem('accessToken')
    if(accessToken) //token是否存在
    {
      let islegal=await axios.post("http://xx",{accessToken:accessToken)})
      if(islegal)
      {
        // token验证通过后开始动态路由配置
        // 查看是否缓存了路由配置
        if(store.state.isnav)
        {
          // 存在路由缓存则可以放行
          next()
        }else{
          // 获取动态配置
          let {data:res} = await axios.get("http:xxxx")
          let nav=res.nav
          })
     		  store.commit("setnav")
          // 添加路由配置
          addRoute(null,nav) //一级动态路由,无父路由传入null
          // 标记路由已缓存
          store.commit("setnav")
          //完成拦截请求并载入路由规则
          next({path:to.path}); //这里并不是放行,而是重新跳转,同router.push()一样
        }
      }else{
        alert('登录已过期!请重新登录')
        this.$router.push({name:"Login"})
      }
    }else{
      alert('非法访问!请先登录')
      this.$router.push({name:"Login"})
    }
  }else{
    // 白名单页面放行
    next()
  }
})

export default router

你可能感兴趣的:(vue技术方案,前端,vue.js,javascript,算法)