vue前端自定义v-xxx指令实现根据用户权限控制元素的显示隐藏

在很多后台管理系统中,常常需要做按钮权限控制。

前端需要根据后端传来的菜单数据控制是否显示某个按钮功能。

新建 permissions.js 文件

//导入vue实例
import Vue from 'vue';

获取储存在vuex中的菜单数据

// 获取当前用户菜单
[types.SET_USER_MENUS] : async({
    commit,
    dispatch
}) = >{
    let {
        body
    } = await userMenusGet() if (body && JSON.stringify(body) !== '{}') {
        permissions.checkKey(body.menuList)
    }
    return body ? body: null
},
//permissions.js 文件

import Vue from 'vue'

let menuList = []

const checkKey = list => {
  // console.log(list, '获取Vuex里的菜单列表')
  menuList = list
  return list
}

export default {
  checkKey
}

遍历菜单数据对比是否有权限

遍历对比name字段是否与传入自定义参数name值相等,匹配成功则表明有权限,则不需要隐藏,返回false,失败没有权限,则返回true,需要隐藏

// 检测传入的元素key是否可以显示
const checkArray = (menuList, name = '', newArr) => {
  newArr = newArr || []
  // 获取权限数组
  // console.log(menuList, '获取权限数组')
  let state = false
  for (let i = 0; menuList && i < menuList.length; i++) {
    const item = menuList[i]
    if (item.nameEn) {
      newArr.push(item.nameEn)
      if (item.hasChildren && item.children.length > 0) {
        checkArray(item.children, name, newArr)
      }
    }
  }
/*   console.log(newArr, 'newArrnewArrnewArrnewArr')
  console.log(newArr.includes(name), '检测++++++++++++++++++++++') */
  newArr.includes(name) ? (state = false) : (state = true)
  return state
}

设置vue自定义指令,注册一个全局自定义指令

/**
 * 使用Vue.directive声明自定义指令v-has
 * inserted:被绑定元素插入父节点时调用
 * el:指令所绑定的元素,可以用来直接操作 DOM
 * binding.value:指令的绑定值,例如:v-has="Home" 中,绑定值为 Home。
 * 使用示例 <el-button v-has="'Home'">权限按钮1</el-button>
 */
Vue.directive('has', {
  inserted: function(el, binding) {
    let permission = binding.value // 获取到 v-has的值
    // console.log(permission, 'permission+++++++++++++++++++++++')
    // 代表某个元素需要通过权限验证
    if (permission) {
      let hasPermission = checkArray(menuList, permission)
      // console.log(menuList, hasPermission, 'hasPermission++++++++++++')
      if (hasPermission) {
        // 没有权限 移除Dom元素
        el.parentNode && el.parentNode.removeChild(el)
      }
    }
  }
})

如果不是按钮,而是要隐藏某个页签可以使用自定义属性,通过v-if判断

/**
 * 如果不是按钮,而是要隐藏某个页签可以使用自定义属性,通过v-if判断
 * 使用示例 <el-tab-pane  label="配置"  v-if="$has('Home')"></el-tab-pane>
 */
Vue.prototype.$has = val => {
  // console.log(val, 'val++++++++++++++++++++++++++++++')
  //最终的结果需要是boolean类型
  return checkArray(menuList, val)
}

使用方式,全局挂载

在 main.js 文件中引入

import permissions from '@/libs/permissions'

使用方式(按钮权限控制隐藏)

<el-button type="primary" v-has="'noVal'">这个按钮不显示</el-button>

使用方式(隐藏某个标签)

<p v-text="这个标签不显示" v-if="$has('noVal')"></p>

最终代码与效果

//创建自定义指令并删除不显示的按钮
import Vue from 'vue'

let menuList = []

const checkKey = list => {
  // console.log(list, '获取Vuex里的菜单列表')
  menuList = list
  return list
}

// 检测传入的元素key是否可以显示
const checkArray = (menuList, name = '', newArr) => {
  newArr = newArr || []
  // 获取权限数组
  // console.log(menuList, '获取权限数组')
  let state = false
  for (let i = 0; menuList && i < menuList.length; i++) {
    const item = menuList[i]
    if (item.nameEn) {
      newArr.push(item.nameEn)
      if (item.hasChildren && item.children.length > 0) {
        checkArray(item.children, name, newArr)
      }
    }
  }
/*   console.log(newArr, 'newArrnewArrnewArrnewArr')
  console.log(newArr.includes(name), '检测++++++++++++++++++++++') */
  newArr.includes(name) ? (state = false) : (state = true)
  return state
}


/**
 * 使用Vue.directive声明自定义指令v-has
 * inserted:被绑定元素插入父节点时调用
 * el:指令所绑定的元素,可以用来直接操作 DOM
 * binding.value:指令的绑定值,例如:v-has="Home" 中,绑定值为 Home。
 * 使用示例 <el-button v-has="'Home'">权限按钮1</el-button>
 */
Vue.directive('has', {
  inserted: function(el, binding) {
    let permission = binding.value // 获取到 v-has的值
    // console.log(permission, 'permission+++++++++++++++++++++++')
    // 代表某个元素需要通过权限验证
    if (permission) {
      let hasPermission = checkArray(menuList, permission)
      // console.log(menuList, hasPermission, 'hasPermission++++++++++++')
      if (hasPermission) {
        // 没有权限 移除Dom元素
        el.parentNode && el.parentNode.removeChild(el)
      }
    }
  }
})

/**
 * 如果不是按钮,而是要隐藏某个页签可以使用自定义属性,通过v-if判断
 * 使用示例 <el-tab-pane  label="配置"  v-if="$has('Home')"></el-tab-pane>
 */
Vue.prototype.$has = val => {
  // console.log(val, 'val++++++++++++++++++++++++++++++')
  //最终的结果需要是boolean类型
  return checkArray(menuList, val)
}

export default {
  checkKey
}

到此结束。

猜你喜欢

转载自blog.csdn.net/weixin_43743175/article/details/127193828