2021-07-06

Vue 前端权限控制的优化改进版

利用Vue的指令,使得权限控制表述更为简洁,无需其它javascript脚本,且解决了class被屏蔽的问题。另外,使用移除元素的方法,避免了与v-if的可见属性的冲突。

1、前言

  之前《Vue前端访问控制方案 》一文中提出,使用class="permissions"结合元素id来标识权限控制相关的dom元素,并通过公共方法checkRights来设置dom元素的可见属性,在实际使用中存在下列问题:

  • checkRights指定上级节点的domKey,结果document.getElementsByClassName获取了更上级的节点或其它子树的节点,没在指定上级节点下,结果节点没找到,导致错误禁用其它节点的权限。
  • style.display与v-if存在可见属性冲突。
  • 更为致命的是,document.getElementsByClassName找不到插槽的节点,如下列形式:
   <el-table-column label="操作">    <template slot-scope="scope">    <el-tooltip effect="dark" content="编辑" id="editUser" placement="left-start">     <el-button size="mini" type="primary" icon="el-icon-edit" circle @click="editUser(scope.row)"></el-button>    </el-tooltip>    <el-tooltip effect="dark" content="禁用" id="disableUser"     placement="left-start" v-if="!scope.row.deleteFlag">     <el-button size="mini" type="primary" icon="el-icon-lock" circle @click="disableUser(scope.row)"></el-button>    </el-tooltip>    <el-tooltip effect="dark" content="启用" id="enableUser"     placement="left-start" v-if="scope.row.deleteFlag">     <el-button size="mini" type="primary" icon="el-icon-unlock" circle @click="enableUser(scope.row)"></el-button>    </el-tooltip>     </template>   </el-table-column>

  此时,document.getElementsByClassName方法找不到class中有permissions的对象。Vue与JQuery的思想有很大不同。

  综上所述问题,因此需要对方案进行优化改进。

2、新的方案

  借鉴v-permission的Vue指令方法,并且不再使用可见属性,而是移除无权限节点的dom元素。具体方案如下:

2.1、定义v-permissions指令

  为区别"v-permission"及":v-permission",这里使用v-permissions。

  创建/src/common/permissions.js文件,代码如下:

import TreeNode from './treeNode.js'/** * 对使用v-permissions指令的dom元素,检查权限;如果无权限,则移除该元素 * 绑定参数形式: * v-permissions 无参数值形式,表示不指定上级节点的domKey * v-permissions="''",设置空串,注意里面需要包含单引号,也是无参数 * v-permissions="'someSuperDomkey'",设置上级节点的domKey,注意里面需要包含单引号 * @param {element对象} el * @param {绑定参数} binding */function checkRights(el,binding){ // 确保权限树已经加载 if (TreeNode.rightsTree == null){ let rights = localStorage.getItem('rights'); if (rights === null || rights === ''){  // 没有权限树,移除当前节点  if(el.parentNode){  el.parentNode.removeChild(el);  }  return; } // 加载权限树 TreeNode.rightsTree = TreeNode.loadData(rights); } // 获取dom元素的id var elementId = el.id; if (elementId == undefined) { console.log("Format error! Without id property of the element with v-permissions:" + el); return; } // 获取上级节点的domkey //console.log(binding); var superDomkey = binding.value; var superNode = null; if(superDomkey != undefined && superDomkey != ""){ // 如果指定上级节点,先查找上级节点 superNode = TreeNode.lookupNodeByDomkey(TreeNode.rightsTree, superDomkey); if (superNode == null){  // 上级key未找到,设置错误  console.log("Wrong superDomkey value for element:" + el);  // 忽略上级节点 } } // 设置搜索的根节点 var rootNode = null; if (superNode == null){ // 上级节点为空 rootNode = TreeNode.rightsTree; } else{ rootNode = superNode; } // 查找当前节点 var node = null; node = TreeNode.lookupNodeByDomkey(rootNode, elementId); if(node == null){ // 如果未在权限树中找到此节点,表示没有权限 // 移除此element对象 if(el.parentNode){  el.parentNode.removeChild(el); }  }}export default { inserted(el,binding) { checkRights(el,binding) }, update(el,binding) { checkRights(el,binding) }}

2.2、注册该指令

  在main.js中,注册该指令。main.js代码如下:

// The Vue build version to load with the `import` command// (runtime-only or standalone) has been set in webpack.base.conf with an alias.import Vue from 'vue'import App from './App'import router from './router'import store from './store'import ElementUI from 'element-ui'import 'element-ui/lib/theme-chalk/index.css'import md5 from 'js-md5';import axios from 'axios'import VueAxios from 'vue-axios'import TreeNode_ from './common/treeNode.js'import CommonFuncs_ from './common/commonFuncs.js'import instance_ from './api/index.js'import global_ from './common/global.js'import permissions from './common/permissions.js'Vue.use(VueAxios,axios)Vue.prototype.$md5 = md5Vue.prototype.TreeNode = TreeNode_Vue.prototype.$baseUrl = process.env.API_ROOTVue.prototype.instance = instance_ //axios实例Vue.prototype.global = global_Vue.prototype.commonFuncs = CommonFuncs_Vue.use(ElementUI)Vue.config.productionTip = false// 注册一个全局自定义指令 v-permissionsVue.directive('permissions', permissions)/* eslint-disable no-new */var vue = new Vue({ el: '#app', router, store, components: { App }, template: '<App/>', render:h=>h(App) })export default vue

2.3、删除checkRights方法

  在commonFuncs.js文件中,删除checkRights方法代码,因为不再调用此方法了。

  原来在App.vue和其它vue文件中调用checkRights方法的代码,也删除。

2.4、模板文件示例

  dom元素如果需要进行权限控制,则使用v-permissions指令,同时还要用id属性,匹配约定的domKey。这样就行了,无需编写其它javascript代码。

2.4.1、App.vue文件

  App.vue文件,代码如下:

<template> <div id="app"> <!-- 其他页 --> <el-container v-if="$route.meta.keepAlive">  <!-- 无头部导航栏 -->  <el-container>  <el-aside :>   <!-- 侧边栏 -->   <keep-alive>   <left></left>   </keep-alive>  </el-aside>  <el-main>   <!-- Body -->   <router-view></router-view>  </el-main>  </el-container>  <!-- 无足部 --> </el-container>  <!-- 登录页 --> <router-view v-if="!$route.meta.keepAlive"></router-view> </div></template><script>import left from './components/Left.vue'export default { name: 'App', components: { left: left }, data(){ return {  collpaseWidth:200 } }, mounted:function(){ }, methods: {  } }</script><style>#app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 20px;}.el-main { padding-top : 0px;}</style>

  现在不需要任何权限控制的代码了。

2.4.2、Left.vue文件

  侧边导航栏组件Left.vue文件,代码如下:

<template> <div > <el-menu :default-openeds="['1']" >  <el-submenu index="1">  <el-menu-item-group >   <el-menu-item index="1-1">   <router-link tag="li" to="/home" exact-active-    id="homeMenu" active->    <i ></i>首页   </router-link>   </el-menu-item>   <el-submenu index="1-2" v-permissions id="userManagementMain">   <template slot="title" ><i ></i>用户管理</template>   <el-menu-item index="1-2-1" v-permissions id="userManagementSub">    <router-link tag="li" to="/userManagement">     <i ></i>用户管理    </router-link>   </el-menu-item>   <el-menu-item index="1-2-2" v-permissions id="changePassword">    <router-link tag="li" to="/changePassword">     <i ></i>修改密码    </router-link>   </el-menu-item>      </el-submenu>   <el-menu-item index="1-3" v-permissions id="questionnaireManagement">   <router-link tag="li" to="/questionnaireManagement">    <i ></i>问卷内容管理   </router-link>   </el-menu-item>   <el-submenu index="1-4" v-permissions id="issueManagementMain">   <template slot="title"><i ></i>问卷发布管理</template>   <el-menu-item index="1-4-1" v-permissions id="issueManagementSub">    <router-link tag="li" to="/issueManagement">     <i ></i>发布问卷查询    </router-link>   </el-menu-item>   <el-menu-item index="1-4-2" v-permissions id="issueTaskQuery">    <router-link tag="li" to="/issueTaskQuery">     <i ></i>发布任务查询    </router-link>   </el-menu-item>   </el-submenu>   <el-menu-item index="1-5" v-permissions id="answerSheetManagement">   <router-link tag="li" to="/answerSheetManagement">    <i ></i>答卷管理   </router-link>   </el-menu-item>       </el-menu-item-group>  </el-submenu> </el-menu> </div></template><style> /* 去掉右边框 */ .el-menu { border-right: none; } .el-submenu { background-color: rgb(231, 235, 220) ; } </style>

  注意,需要权限控制的dom元素,都有v-permissions,并且有id的值。

2.4.3、业务模块vue模板示例

  业务模块vue模板示例,代码如下:

<template> <div id="contentwrapper"> <el-form ref="form" :model="formData" label-width="80px">  <el-card>  <el-row>   <!--占整行-->   <el-col :span="24">    <h5 align=left>用户管理 / 用户管理</h5>   <!-- 分隔线 -->   <el-divider></el-divider>   </el-col>      </el-row>  <el-row>   <el-col align="left" :span="6">   <el-button type="primary" v-permissions="'userManagementSub'" id="addUser" size="small" @click="addUser">    <i ></i>添加用户   </el-button>   </el-col>   <!-- 查询条件 -->   <el-col align="left" :span="6">   <el-form-item label="用户类型:" label-width="100px">    <el-select v-model="formData.userTypeLabel" size="small" @change="selectUserType">    <el-option     v-for="(item,index) in userTypeList"     :key="index"     :label="item.itemValue"     :value="item"    />    </el-select>        </el-form-item>   </el-col>   <el-col :span="6">   <el-form-item label="用户状态:" label-width="100px">    <el-select v-model="formData.userStatusLabel" size="small" @change="selectUserStatus">    <el-option     v-for="item in userStatusList"     :key="item.itemKey"     :label="item.itemValue"     :value="item"    />    </el-select>        </el-form-item>    </el-col>    <el-col align="right" :span="6">   <el-button type="primary" v-permissions="'userManagementSub'" id="queryUser" size="small" @click="queryUsers">    <i ></i>查询   </el-button>   </el-col>      </el-row>  <!-- 用户列表数据 -->  <el-table :data="userInfoList" border stripe :row-   :cell-   :header-cell->   <el-table-column label="用户ID" width="60px" prop="userId"></el-table-column>   <el-table-column label="用户类型" width="100px" prop="userType">   <template slot-scope="scope">    <span v-if="userTypeMap.get(scope.row.userType) != null">    {{userTypeMap.get(scope.row.userType).itemValue}}    </span>   </template>      </el-table-column&g......

原文转载:http://www.shaoqun.com/a/849277.html

跨境电商:https://www.ikjzd.com/

白色清关:https://www.ikjzd.com/w/1410

etoro:https://www.ikjzd.com/w/1402

c88:https://www.ikjzd.com/w/1017


利用Vue的指令,使得权限控制表述更为简洁,无需其它javascript脚本,且解决了class被屏蔽的问题。另外,使用移除元素的方法,避免了与v-if的可见属性的冲突。1、前言  之前《Vue前端访问控制方案》一文中提出,使用class="permissions"结合元素id来标识权限控制相关的dom元素,并通过公共方法checkRights来设置dom元素的可见属性,在实际使用中存在下列问题:
asinseed:https://www.ikjzd.com/w/533
环球华网:https://www.ikjzd.com/w/1063
2019年独立站推广引流怎么做?当然是选Reddit了:https://www.ikjzd.com/articles/91249
愿谈则谈,要打便打!:https://www.ikjzd.com/articles/91251
关于亚马逊禁售和限制性销售商品的相关信息:https://www.ikjzd.com/articles/91253
亚马逊Prime Day秒杀活动还没申报?错过再等一年!:https://www.ikjzd.com/articles/91254
少妇口述:好色男邻居趁老公出差跟我一夜情:http://lady.shaoqun.com/a/70312.html
学长我们去厕所里做好不好 小东西是不是又想要了:http://www.30bags.com/m/a/249829.html
深圳沙湾往事舞剧演出延期(附重新演出时间):http://www.30bags.com/a/474657.html
深圳第71届西部车展需要报名吗:http://www.30bags.com/a/474658.html
"做事"后有五个症状,说明太频繁了!看看你有没有:http://lady.shaoqun.com/a/403805.html
女性性生活过多的症状!每个年龄段的正常性生活频率是多少?:http://lady.shaoqun.com/a/403806.html

No comments:

Post a Comment