Vue

Vue 动态注册路由(addRouter添加路由)

联系站长 作者:web知道 来源:未知 2019-06-12 15:02 我要评论

在日常开发时,我们需要做到权限这块,那么我们就得实现路由动态添加...

==================== 模拟权限操作 ====================

Login.vue
//正常登陆页跳转到指定页面
this.$router.push('/home')
 
//实现登陆不跳转到指定的页面,而跳转到指定路由的需求
// this.$router.push('/awfifnypm')

Main.js
引入
import jurisdiction from '@/api/transitionComponent.js'   //用于转换component
import { exRouters } from '@/views/login/navdata.js'   //用于模拟返回数据   真正开发,用接口请求

// 设置全局守卫
router.beforeEach((to, from, next) => {

判断VUEX有没有路由数组数据
if (store.state.oneRouter.length === 0) {

     //此处发请求获取路由信息

     //把后端返回的路由拼接成结构树
     function getTree(data, parentId) {
         var newArr = []
         data.forEach((item) => {
                  if(item.parentId == parentId){
                           item.children = this.getTree(data, item.menuId)
                           newArr.push(item)
                  }
         })
         return newArr
    }

   var exRouter = this.getTree(exRouters, -1)
 

    //由于数据返回的component是字符串,我们需要转换成函数   这里为三级路由,如果有四级还需要再做判断
    for(var val of exRouter){
        val.component = jurisdiction(val.component)
        if(val.children != undefined){
            for(var el of val.children){
                el.component = jurisdiction(el.component)
                    if(el.children != undefined){
                        for(var hi of el.children){
                            hi.component = jurisdiction(hi.component)
                    }
                }
            }
        }
    }

===递归的方式转换========================================
import jurisdiction from '@/api/transitionComponent.js'
for(var val of exRouter){
     val.component = jurisdiction(val.component)
     recursion(val)
}

方法
recursion=(data)=>{
      if(data.children != undefined){
             for(var el of data.children){
                    el.component = jurisdiction(el.component)
                    recursion(el)
            }
     }
}
=======================================================
 
    
    //把返回数据传到vuex,成功后添加到路由
    store.dispatch('awfifnypm', {exRouter}).then(function (data) {
     //注入时拼接404处理路由
    router.addRoutes(exRouter.concat([{
        path: '*',
        redirect: '/404'
        }]))
        router.options.routes.push(...exRouter)
    })
}

//实现登陆不跳转到指定的页面,而跳转到指定路由的需求
//if (token) {
   // if(to.path == '/awfifnypm'){
   // next({path:exRouter[0].path})
   // }else{
   // next()
   // }
//} else {
   // 如果没有token,判断如果是to到/login,next往下执行
   //if (to.path === '/') {
   //next() // 往下执行
   //} else {
   // 如果没有token,且不是进行登陆操作,则重定向到/login
   //next({path: '/'})
   //}
//}
 
})

Store.js
const store = new Vuex.Store({
  // 定义状态
  state: {
    oneRouter: []
  },
  mutations:{
      getRouter (state, addroutes) {
         state.oneRouter = addroutes
    },
  },
  actions: {
    awfifnypm (context, addroutes) {
      context.commit('getRouter', addroutes)
    }
  }
})
 
export default store

transitionComponent
//用于转换component

export default (name) => (resolve) => 
require ([`@/views/${name}.vue`], resolve)

Router.js
export default new Router({
    routes: [
     { 
        path: '/',
        name:"登陆",
        component: () =>
        import('@/views/login/login'),
        hidden: true
     },
    {
        path: '/404',
        name: 'HelloWorld',
        component: ErrorPage,
        hidden: true
    },
  ]
})
 

navData.js 模拟返回数据
路径是大坑,切记切记

export const exRouter = [
   {
      path: '/home',
      component: 'layout/layout',
      redirect: '/home',
      name: 'home',
      meta: {
         title: "首页"
      },
      hidden: true,
         children: [{
         path: '/home',
         component: 'home/index',
      }]
   },
   {
      path: "/dms",
      component: 'layout/layout',
      meta: {
         title: "会员管理"
      },
      children: [{
         path: "search",
        meta: {
            title: "会员综合资料查询"
         },
         component: 'dms/index',
      }]
      },
   {
      path: "/oms",
      component: 'layout/layout',
      meta: {
         title: "订单管理"
      },
      children: [{
         path: "search_common",
      meta: {
         title: "订单查询"
      },
      component: 'oms/search_common',
   },
   {
      path: "search_th",
      meta: {
         title: "退货单查询"
      },
      component: 'oms/search_th',
   },
   {
      path: "search_bd",
      meta: {
         title: "补单查询"
      },
      component: 'oms/search_bd',
   },
   {
      path: "search_tc",
      meta: {
         title: "调差单查询"
      },
      component: 'oms/search_tc',
   }
   ]
  },

  //实现登陆不跳转到指定的页面,而跳转到指定路由的需求
  // {
      // path: '/awfifnypm',
      // meta: {
          // title: "空白"
      // },
      // hidden: true,
      // component: 'home/index',
  // },
 
]




==================== 线上权限操作 ====================
如果可以,尽量不使用返回数据结构方法实现权限,使用返回权限菜单名方式实现

Login.vue
this.axios.post("/login",{
     username: this.userName,
     password: this.passWord
}).then((res) => {
     if(res.data.code == 200){
          sessionStorage.setItem("token", res.data.data.access_token)
          sessionStorage.setItem("refresh_token", res.data.data.refresh_token)
          this.$router.push('home')
     }else{
          this.$message({
          message: res.data.msg,
          type: 'warning'
          })
     }
})

Main.js
引入
import {DataConstruction} from '@/api/prs.js'
import { getUserMenuList,getUserInfos } from "@/api/power"    //这里只是单纯的接口请求取数据
 

function getRightBtn(params){
//获取当前访问的页面,并取出当前页面的权限标识
var arr = params
if(arr.length > 0 ){
/**权限指令**/
     Vue.directive('has', {
          bind: function(el, binding) {
              if (!Vue.prototype.$_has(binding.value)) {
                   el.parentNode.removeChild(el);
              }
          }
     })
//权限检查方法
     Vue.prototype.$_has = function(value) {
          let isExist=false;
          let myRight = arr[arr.length - 1].meta.buttonRight
          let buttonpermsStr=myRight.join('');
          if(buttonpermsStr==undefined || buttonpermsStr==null || buttonpermsStr==''){
               return false;
          }
          for(let i=0;i<myRight.length;i++){
               if(myRight[i].indexOf(value) > -1){
                    isExist=true;
                    break;
               }
          }
          return isExist;
          };
     }
}


router.beforeEach((to,from,next)=>{
     var token = sessionStorage.getItem('token')
     if(token){
          if (store.state.oneRouter.length == 0) {
          //获取用户信息
               getUserInfos().then(res=>{
                    if(res.data.code == 0){
                         store.dispatch('setUserInfo', res.data.data.sysUsers)
                    }
               })
               getUserMenuList().then((res) => {
                    if(res.data.code == 0){
                         let transferData = DataConstruction(res.data.data) 
                         store.dispatch('rightsRouter', {transferData})
                         .then(function () {
                              router.addRoutes(transferData.concat([{
                                   path: '*',
                                   redirect: '/404'
                              }]))
                              router.options.routes.push(...transferData)
                         })
                    }
                    getRightBtn(to.matched)
                    next()
              })
          }else{
              getRightBtn(to.matched)
               next()
         }
     }else{
          if (to.path === '/login') {
               next()
          } else {
               next({name: 'Login'})
         }
     }
})
 

DataConstruction  数据转换
//转换层级
let getTree = function(data, parentId) {
     var newArr = []
     data.forEach((item) => {
          if(item.parentId == parentId){
               item.children = getTree(data, item.menuId)
               newArr.push(item)
          }
     })
     return newArr
}
 
//分层级前先处理数据,转换成需要的路由结构,组件转换
export const DataConstruction = function(data){
     let temporaryArr = []
     data.forEach(item=>{
          temporaryArr.push({
               path:item.path,
               name:item.name,
               meta:{
                    title:item.title,
                    isShow:item.visible, //1为显示,0为隐藏
                    icon:item.icon,
                    sort:item.sort,
                    buttonRight:buttonData(item.buttons)
               },
               component:jurisdiction(item.component),
               parentId:item.parentId,
              menuId:item.menuId,
               type:item.type //1是按钮,0是菜单
          })
     })
     return getTree(temporaryArr, -1)
}
 
//处理权限按钮数据
let buttonData = function(data){
     let temporaryArr = []
     if(data.length > 0){
          data.forEach(item=>{
               temporaryArr.push(item.permission)
          })
     }
     return temporaryArr
}
 

Store.js
const store = new Vuex.Store({
  // 定义状态
  state: {
    oneRouter: []
  },
  mutations:{
      getRouter (state, addroutes) {
         state.oneRouter = addroutes
    },
  },
  actions: {
    rightsRouter (context, addroutes) {
      context.commit('getRouter', addroutes)
    }
  }
})
 
export default store

jurisdiction
//用于转换component

export default (name) => (resolve) => 
require ([`@/views/${name}.vue`], resolve)

Router.js
export default new Router({
    routes: [
     { 
        path: '/',
        name:"登陆",
        component: () =>
        import('@/views/login/login'),
        hidden: true
     },
     {
        path: '/',
        component: Layout,
        redirect: '/login',
        name: 'kernel',
        meta: {
             title: "完美核心"
        },
        hidden: true,
        children: [{
                path: 'home',
                meta: {
                        title: "首页"
                },
                component: () =>
                import('@/views/home')
        }]
     },
    {
        path: '/404',
        name: 'HelloWorld',
        component: ErrorPage,
        hidden: true
    },
  ]
})
 




本文如有侵犯版权请联系站长删除。

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源;3.作者投稿可能会经我们编辑修改或补充。

相关文章
网友点评