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

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

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

网上很多问权限的问题,但几乎找不到很好的解决答案,在很长一段时间里,非常打击使用vue技术栈开发的信心。最有质量的一篇文章是:http://www.jb51.net/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代码暂不能全部公开,有问题可留言。

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

(0)

相关推荐

  • vue-router 权限控制的示例代码

    最近搭建了公司的后台管理系统, 而且系统还比较庞大, 要实现以下几点: 菜单权限, 根据不同权限显示不同的菜单 操作权限, 比如有些账号没有新增权限, 有些没有修改或者删除权限 数据权限, 比如统计概况, 普通管理员不能看到公司营业概况,但能看到自己所属区域的概况 显示权限, 比如列表, 运营能看到那一列的签约金额,但市场不能看到签约金额这一列 到目前为止还在构建中, 已经解决菜单权限和操作权限. 菜单权限: 最开始的时候也是按照楼上给出的方法,本地先配置一套路由,然后登陆成功后会从服务器返回一

  • 详解基于Vue/React项目的移动端适配方案

    前言 本文的目标是通过下文介绍的适配方案,使用vue或react开发移动端及H5的时候,不需要再关心移动设备的大小,只需要按照固定设计稿的px值布局,提升开发效率. 下文给出了本人分别使用create-react-app搭建的react(create-react-app)项目和使用vue-cli 2.x 搭建的vue项目中的 亲测可用 配置方案. px2rem或postcss-px2rem 在移动端中,为了设配不同的设备,通常使用rem来做适配. rem是通过根元素进行适配的,网页中的根元素指的

  • 详解基于Vue cli开发修改外部组件Vant默认样式

    前言 在引入外部组件的时候,想要修改默认样式,可以通过class修改,但一般会有权重不够等各种原因,官网其实列出了一套主题定制的方案,通过覆盖配置文件来修改样式,官网地址:主题定制 提示:以下是本篇文章正文内容,下面案例可供参考 一.Less 因为Vant 使用了 Less 对样式进行预处理,并内置了一些样式变量,可以通过替换样式变量即可定制你自己需要的主题. 给你的项目配置less: npm install less --save-dev npm install less-loader --s

  • 基于Vue实现后台系统权限控制的示例代码

    用Vue/React这类双向绑定框架做后台系统再适合不过,后台系统相比普通前端项目除了数据交互更频繁以外,还有一个特别的需求就是对用户的权限控制,那么如何在一个Vue应用中实现权限控制呢?下面是我的一点经验. 权限控制是什么 在权限的世界里服务端提供的一切都是资源,资源可以由请求方法+请求地址来描述,权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源.具体的说,前端对资源的访问通常是由界面上的按钮发起,比如删除某条数据:或由用户进入某一个页面发起,比如获取某个列表数据

  • 详解基于vue的移动web app页面缓存解决方案

    现在移动web app越来越热门了,许多公司开始尝试使用angular.react.vue等MVVM框架来开发单页架构的web app.但在开发web app时,如果希望页面的导航体验也接近原生应用,那一般都会遇到这两个问题: 识别前进后退行为 后退时恢复之前的页面 笔者开发了一个基于vue与vue-router的导航库vue-navigation,来帮助开发者来解决这些问题,下面是问题的解决思路. 识别前进后退 先说第一个问题.和原生app不一样,浏览器中主要有这几个限制: 没有提供前进后退的

  • 详解基于vue的服务端渲染框架NUXT

    Nuxt 随着现在vue和react的流行,许多网站都做成了SPA,确实提升了用户体验,但SPA也有两个弱点,就是SEO和首屏渲染速度.为了解决单页应用的痛点,基于vue和react的服务端渲染应运而生.由于公司的框架采用的是vue,所以就简单的研究了一下基于vue的服务端渲染框架--NUXT.在vue的官网有关于服务端渲染的详细介绍,而NUXT集成了利用Vue开发服务端渲染的应用所需要的各种配置,也集成了Vue2.vue-router.vuex.vux-meta(管理页面meta信息的),利用

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

    使用vue开发带权限管理系统,尤其是采用了vue-router做路由,很多人都遇到的一个问题就是如何动态加载路由path对应的component. 典型的应用场景就是:前端菜单不静态的写在vue程序里,而是要从后台程序和数据库返回的菜单来动态加载到vue应用中. 网上很多问权限的问题,但几乎找不到很好的解决答案,在很长一段时间里,非常打击使用vue技术栈开发的信心.最有质量的一篇文章是:http://www.jb51.net/article/124801.htm 但作者并没有完全解决这个问题,还

  • 详解基于Vue,Nginx的前后端不分离部署教程

    有小伙伴私信问我vue项目是如何进行前后端不分离打包发布的,那我岂能坐视不管,如此宠粉的我肯定是要给发一篇教程的,话不多说,开始操作 前端假如我们要发布我们的Vue项目,假设我们前端用的是history路由(要发就发个全套的),并且在后端带有一个二级目录,以便于可以在服务器上部署N个项目,在这里后台服务器的话,我用Nginx服务器来给大家模拟,接下来就面对疾风吧: 一.在这里我前端vue项目使用vue cli脚手架进行搭建的,后台使用Nginx,首先是前端配置: 1.前端配置,在这里假如后端访问

  • 详解使用Vue Router导航钩子与Vuex来实现后退状态保存

    不好意思,标题比较啰嗦,因为这次的流水账确实属于一个比较细节的小东西,下面详细讲: 1需求 最近在使用electron-vue开发一个跨平台的桌面端软件,刚上手写了几个页面,遇到一个问题:桌面端软件通常会有导航需求,类似下图 导航按钮 点击返回按钮,返回上一页,并且显示上页内容.其实不止App,即使普通的网页中也会有此类需求,尤其是使用vue写SPA时. 项目中的导航几乎都是采用router.push({name: 'xxx', params: {xxx:123...}})这种方式.这种方式导致

  • 详解基于Vue+Koa的pm2配置

    目前使用的技术栈是:前端Vue.后端Koa.数据库Mongodb. 然而每当起服务的时候,都要 npm start . node ./server/app.js ,还要同时保持这两个窗口一直是开着的,很是麻烦. 而且因为我使用的是koa,也没有使用狼叔写的koa脚手架.是自己基于廖雪峰老师的 Koa框架 改的一个小型mvc.导致没有热更新. 为了简化这种没必要的操作及增加热更新,开始想怎么进行优化.于是选择了 pm2 配置pm2 先安装pm2: npm i pm2 . npm i pm2 -g

  • 详解基于spring多数据源动态调用及其事务处理

    需求: 有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个.即同时保持多个数据库的连接,在方法中根据传入的参数来确定. 下图的单数据源的调用和多数据源动态调用的流程,可以看出在Dao层中需要有一个DataSource选择器,来确定到底是调用哪个数据源. 实现方式 对Dao层提供一个公共父类,保持有多个数据源的连接(本人是基于iBatis,即保持多个SQLSessionTemplate) /** * Created by hzlizhou on 2017/2/6. */ p

随机推荐