详解基于vue-router的动态权限控制实现方案


Posted in Javascript onSeptember 28, 2017

使用vue开发带权限管理系统,尤其是采用了vue-router做路由,很多人都遇到的一个问题就是如何动态加载路由path对应的component。

典型的应用场景就是:前端菜单不静态的写在vue程序里,而是要从后台程序和数据库返回的菜单来动态加载到vue应用中。

网上很多问权限的问题,但几乎找不到很好的解决答案,在很长一段时间里,非常打击使用vue技术栈开发的信心。最有质量的一篇文章是:https://3water.com/article/124801.htm

但作者并没有完全解决这个问题,还留有几个问题是:

1)登录之后跳转到首页,此时路由已经是加载完成的了不能更改,菜单可以显示但是没有路由。

2)前端应用人为刷新网页路由产生某些问题。

本文即在这篇文章的基础上对这两个问题解决,以使其完整。

前提是认真拜读上面提到的那篇文章,下面直接用代码说话:

问题1的解决思路:

登录之后跳转到首页,router是vue应用的router 引入进登录方法,在登录之后跳转之前对router进行改变,改变要点1是精确赋值到router的routes具体地方,比如我这里是routes[0]的子路由,2是用addRoutes函数使其生效。

登录功能的js

export const login = ({commit}, data) => { Service.post('/login', Qs.stringify(data))
  .then(res => {
   const success = Object.is(res.statusText, 'OK') && Object.is(res.data.code, '0')
   if (success) {
    var menus = generateMenus(res.data.menus)
    window.sessionStorage.routes = JSON.stringify(menus)
    if (menuModule.state.items.length <= 0) { // 避免注销后在不刷新页面的情况下再登录重复加载路由
     commit(types.ADD_MENU, menus)
     // 动态加载路由关键2行
     router.options.routes[0].children.push(...generateRoutesFromMenu(menuModule.state.items))
     router.addRoutes(router.options.routes)
    }
    window.sessionStorage.loginName = data.loginName
    router.push({path: '/'})
   } else {
    commit('loginErr', res.data.msg)
   }
  })
}


function generateRoutesFromMenu (menu = [], routes = []) {
 for (let i = 0, l = menu.length; i < l; i++) {
  let item = menu[i]
  if (item.path) {
   routes.push(item)
  }
  if (!item.component) {
   item.component = resolve => require([`views/` + item.component + `.vue`], resolve)
   generateRoutesFromMenu(item.children, routes)
  }
 }
 return routes
}

问题2的解决思路:

是不在主app里引入实例化vue-router的js,而是直接在app里实例化router,目的就是网页刷新的时候每次都确保生成动态的router。

app.js部分代码:

Vue.use(Router)
let menus = window.sessionStorage.routes //登录成功返回的菜单
if (menus) {
 let items = JSON.parse(menus)
 store.commit(ADD_MENU, items)
}

const router = new Router({
 mode: 'hash',
 linkActiveClass: 'is-active',
 scrollBehavior: () => ({ y: 0 }),
 routes: [
  {
   name: 'Main',
   path: '/',
   component: require('views/Main.vue'),
   children: [ //动态路由之所以作为Main的子路由是基于:登录之后跳转到Main主页,该主页是类似于frame的页面加载框架,只有将动态路由作为Main的子路由才能确保其他页面显示到Main框架内。
    ...generateRoutesFromMenu(menuModule.state.items)
   ]
  },
  {
   name: 'Login',
   path: '/login',
   component: require('views/Login.vue')
  }
 ]
})

function generateRoutesFromMenu (menu = [], routes = []) {
 for (let i = 0, l = menu.length; i < l; i++) {
  let item = menu[i]
  if (item.path) {
   routes.push(item)
  }
  if (!item.component) {
   item.component = resolve => require([`views/` + item.component + `.vue`], resolve)
   generateRoutesFromMenu(item.children, routes)
  }
 }
 return routes
}

另附menu items代码

const state = {
 items: [ // 什么菜单都不定义,完全由后端返回
 ]
}
const mutations = {
 [types.ADD_MENU] (state, menuItems) {
  if (menuItems.length > 0) {
   menuItems.map(function (item) {
    item.children.map(function (child) {
     child.component = lazyLoading(child.component)
    })
   })
   state.items.push(...menuItems)
  }
 },

lazyloding

export default (name, index = false) => () => import(`views/${name}${index ? '/index' : ''}.vue`)

git代码暂不能全部公开,有问题可留言。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
对象的类型:本地对象(1)
Dec 29 Javascript
js各种验证文本框输入格式(正则表达式)
Oct 22 Javascript
js异步加载的三种解决方案
Mar 04 Javascript
JavaScript中的ubound函数使用实例
Nov 04 Javascript
iframe跨域通信封装详解
Aug 11 Javascript
javascript轻量级库createjs使用Easel实现拖拽效果
Feb 19 Javascript
什么是JavaScript注入攻击?
Sep 14 Javascript
Javascript设计模式之装饰者模式详解篇
Jan 17 Javascript
AngularJs上传前预览图片的实例代码
Jan 20 Javascript
bootstrap suggest下拉框使用详解
Apr 10 Javascript
[原创]jquery判断元素内容是否为空的方法
May 04 jQuery
npm 语义版本控制详解
Sep 10 Javascript
node.js学习之断言assert的使用示例
Sep 28 #Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 #Javascript
node.js学习之事件模块Events的使用示例
Sep 28 #Javascript
es6中的解构赋值、扩展运算符和rest参数使用详解
Sep 28 #Javascript
JS获取日期的方法实例【昨天,今天,明天,前n天,后n天的日期】
Sep 28 #Javascript
jquery实现左右轮播图效果
Sep 28 #jQuery
bootstrap table实现点击翻页功能 可记录上下页选中的行
Sep 28 #Javascript
You might like
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
Symfony生成二维码的方法
2016/02/04 PHP
PHP PDOStatement::setAttribute讲解
2019/02/01 PHP
在Laravel的Model层做数据缓存的实现
2019/09/26 PHP
PHP网页缓存技术优点及代码实例
2020/07/29 PHP
js复制网页内容并兼容各主流浏览器的代码
2013/12/17 Javascript
JS+JSP通过img标签调用实现静态页面访问次数统计的方法
2015/12/14 Javascript
详解JavaScript异步编程中jQuery的promise对象的作用
2016/05/03 Javascript
Bootstrap Paginator分页插件与ajax相结合实现动态无刷新分页效果
2016/05/27 Javascript
jQuery实现最简单的切换图效果【可兼容IE6、火狐、谷歌、opera等】
2016/09/04 Javascript
Vue.2.0.5实现Class 与 Style 绑定的实例
2017/06/20 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
原生js jquery ajax请求以及jsonp的调用方法
2017/08/04 jQuery
JavaScript实现指定数量的并发限制的示例代码
2020/03/10 Javascript
微信小程序开发打开另一个小程序的实现方法
2020/05/17 Javascript
基于JavaScript实现大文件上传后端代码实例
2020/08/18 Javascript
[00:50]深扒TI7聊天轮盘语音出处6
2017/05/11 DOTA
python实现二叉树的遍历
2017/12/11 Python
Python获取二维矩阵每列最大值的方法
2018/04/03 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
10个Python面试常问的问题(小结)
2019/11/20 Python
如何给Python代码进行加密
2020/01/10 Python
Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]和X[:,:,m:n]
2020/02/13 Python
python用WxPython库实现无边框窗体和透明窗体实现方法详解
2020/02/21 Python
Wilson体育用品官网:美国著名运动器材品牌
2019/05/12 全球购物
Chupi官网:在爱尔兰手工制作的订婚、结婚戒指和精美珠宝
2020/09/28 全球购物
同事打架检讨书
2014/02/04 职场文书
城市规划应届生推荐信
2014/09/08 职场文书
会计学习心得体会
2014/09/09 职场文书
团代会闭幕词
2015/01/28 职场文书
求职意向书范本
2015/05/11 职场文书
2015小学教师年度考核工作总结
2015/05/12 职场文书
学生病假条怎么写
2015/08/17 职场文书
HTML5简单实现添加背景音乐的几种方法
2021/05/12 HTML / CSS
使用CSS3实现按钮悬停闪烁动态特效代码
2021/08/30 HTML / CSS
不负正版帝国之名 《重返帝国》引领SLG手游制作新的标杆
2022/04/07 其他游戏