10

索引

概述

关于动态路由的相关处理,请参考本人的另一篇文章vue.js前后端分离后台,该如何根据用户权限处理前端显示和后台接口访问,本文作为上一篇的续作
有时候仅处理菜单,是不够的,很多情况下,有读的权限,但无写的权限的时候,就需要更灵活的控制。也就是这篇文章的由来。

大概有两种方式可以使用:

  1. 指令
  2. 组件

基于指令

关于指令的使用,网上的文章比较多了,主要是操作DOM,把没有权限的元素从已渲染的画面里面删除。这里只是简单的出个示范,具体可以参考自己的授权系统开发:

import Vue from 'vue'
// import Store from '../store/'

const directives = {
  role: {
    // 指令的定义 (TBD:有没有before'inserted'这样的钩子函数用?)
    inserted: (el, binding, vnode) => {
      // 权限
      if (binding.value && [处理权限的判定]) {
        el.parentElement.removeChild(el)
      }
    }
  }
}

Object.keys(directives).forEach(key => {
  Vue.directive(key, directives[key])
})
<el-button type="success" icon="el-icon-document" size="small" v-role="xxx-upload"
                   @click="$router.push({name: 'music-album-multi-upload'})">上传
        </el-button>

基于组件

不确定对于vue组件,有没有全局的生命周期钩子,如果有的话,处理起来就更方便了。
下面就以普通的组件形式来说明下处理过程:

写一个全局的组件,注册为v-sec,其中参数code为访问当前画面segment的授权码。

<template>
  <div>
    <slot v-if="permitted"></slot>
  </div>
</template>

<script>
  import vuet from '@/vuet/'

  export default {
    name: "sec",
    props: {
      code: {
        type: String,
        required: true,
        default: 'text'
      },
    },
    data() {
      return {
        permitted: false
      }
    },
    beforeCreate() {
      let userSelf = vuet.getModule('user-self')
      if (userSelf /* && userSelf.secCodes && userSelf.secCodes.contains(this.code) */) {
        this.$nextTick(function () {
          this.permitted = true
        })
      }
    }
  }
</script>

然后在画面上使用

<v-sec code="xxx-add">
  <el-button type="success" icon="el-icon-document" size="small"
             @click="$router.push('/sys/module/add')">添加
  </el-button>
</v-sec>

与指令的那种方式在使用方面差不多,如果组件的这种方式能避免内嵌的组件被渲染,那效果会比指令的那种好一些。

接下来,在项目只可能就两种方式分别做实验。

权限的定义

画面

一般通过导航+动态路由能控制住的,像画面和菜单。
然后配合路由的全局函数router.beforeEach基本上比较好实现。
为了配合动态路由,需要指定以下几个字段

  • 路径,用于画面跳转,
  • 组件名/文件地址,用于路由生成,指向实际的vue文件(我们可以约定-代替路径分隔符:common-main=/src/pages/common/main.vue)
  • 画面名,用于显示,导航或Title等地方需要
  • icon,有一些样式库里有这个,作为可选项
  • show_nav,是否显示在导航中,有一些画面需要参数的话,不能够直接从导航进入,可区分开

页面片段

基本上标记个名字,与画面关联起来以便于管理就可以了。
然后配置后台管理系统,可以通过先通过后台录入画面及画面片段,然后用程序生成对应的vue文件及部分代码。这样子开发效率是不是高一些?

  • 画面ID
  • 片段编码,不直接使用DB的ID自增,以避免在不同的系统间数据迁移时的问题。
  • 片段名,在授权画面展示以方便管理

授权

授权时,把画面和画面片段与角色关联即可,然后用户在登录后获取到角色,再从内存/DB/缓存中把角色对应的画面和菜单等权限查出,合并到一起返回给vue。vue拿到数据后,缓存到localstorage以避免画面的刷新(f5/浏览器刷新)后出现404的问题,这一点在上一篇里面已经说明过了。


ccfish
1.2k 声望56 粉丝

专业救火员 专治各种不服。