vue3+element-plus权限控制实现(el-tree父子级不关联情况处理)

简介: 后台管理系统常见的权限控制需求,这里讲button实现交互细节处理,取消选中子级menu/button,父级不关联取消;选中/取消父级catalog/menu,子级全部选中/取消;选中/取消部分子级menu/button,父级关联半选中状态(indeterminate=true);


@[TOC](文章目录)


---


# 前言

在开发后台管理系统的时候,用户的权限控制是一个常见的需求。这里需要探讨下按钮的级别的权限控制,以及实现中使用element-plus tree 组件的使用细节。


---

# 一、遇到的交互场景

基于原有的基础上实现按钮级别的权限控制,原有的如下图每一个菜单都有一个唯一ID,PID(父级ID),现在需要扩展的功能,就是添加一个button按钮控制,其中主要的细节交互:


1. **取消选中**子级menu/button,父级不关联取消;

2. **选中/取消**父级catalog/menu,子级全部选中/取消;

3. **选中/取消**部分子级menu/button,父级关联半选中状态(indeterminate=true);


其中我用的是el-tree 组件,我用button:xxx业务按钮;这样的方式来命名,后端也给了区分类型的字段type:catalog(目录),menu(菜单),button(按钮)。


![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/ba644e0f0bcd4ddf938d1bed15027e2a.png)

### el-tree 中 check-strictly 属性

el-tree 中 check-strictly 属性,为了实现**取消选中**子级menu/button,父级不关联取消,这里check-strictly设置为true;设置后点击父级也不关联子级选中了,用户用起来不方便,这里就需要我们自己处理

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/43d3b00241164edfb7fc2853be9846c6.png)


# 二、处理父级的半选中以及选中交互

### el-tree

```html

<el-tree

           ref="treeRef"

           :check-strictly="true"

           :data="treeData"

           show-checkbox

           default-expand-all

           node-key="id"

           highlight-current

           :default-checked-keys="variable.roleForm.featureIds"

           :props="defaultProps"

           @check="hanleCheck"

           @check-change="checkChange"

         />

```

```js

const defaultProps = {

 children: 'children',

 label: function (treeData: any, treeNode: any) {

   return treeData?.name

 }

}

```

### check,check-change 事件

这里主要用的事件 check,check-change

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/d38901b7e13f4eb9903ecc02e9cd6e5e.png)


```js

const hanleCheck = (data:any, node:any) => {

 console.log(data, node);

 // 获取当前节点是否被选中

 const isChecked = treeRef.value!.getNode(data).checked

 // 如果当前节点被选中,则遍历下级子节点并选中,如果当前节点取消选中,则遍历下级节点并取消

 if (isChecked) {

   // 判断该节点是否有下级节点,如果有那么遍历设置下级节点为选中

   data.children && data.children.length > 0 && setChildreChecked(data.children, true)

 } else {

   // 如果节点取消选中,则取消该节点下的子节点选中

   data.children && data.children.length > 0 && setChildreChecked(data.children, false)

 }

 function setChildreChecked(node:any, isChecked:boolean) {

   node.forEach((item:any) => {

     item.children && item.children.length > 0 && setChildreChecked(item.children, isChecked)

     // // 修改勾选状态

     treeRef.value!.setChecked(item.id, isChecked,false)

   })

 }

}


const checkChange = (data, checked, indeterminate) => {

     // console.log(data, checked, indeterminate);

     // 选中全部子节点,父节点也默认选中,但是子节点再次取消勾选或者全部子节点取消勾选也不会影响父节点勾选状态

     let checkNode = treeRef.value!.getNode(data)//获取当前节点

     // 勾选部分子节点,父节点变为半选状态

     if (checkNode.parent && checkNode.parent.childNodes.some(ele => ele.checked)) {

       checkNode.parent.indeterminate = true

     }

     // 勾选全部子节点,父节点变为全选状态

     if (checkNode.parent && checkNode.parent.childNodes.every(ele => ele.checked)) {

       checkNode.parent.checked = true

       checkNode.parent.indeterminate = false

     }

     // 如果取消所有第二节点的勾选状态,则第一层父节点也取消勾选

     if (checkNode.level == 2 && checkNode.parent.childNodes.every(ele => !ele.checked)) {

       checkNode.parent.checked = false

       checkNode.parent.indeterminate = false

     }

}


```

其中,上面用的

```js

     treeRef.value!.setChecked(item.id, isChecked,false)

```

看文档说第三个属性是是否要递归,我觉得是设置了true后,应该帮我递归选中/取消关联的节点,但没有生效,所以还是自己递归下;**(有大佬能指出是我的用法有问题吗?劳烦指出)**

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/74bec0b2b8714f6698c6e75bf187bcb4.png)

### 编辑进来,父级的半选状态处理

上述方法实现后,我们就可以实现上述交互了,但这里要注意的一点,就是点击编辑进入的,父级的半选状态没有选中,也就是说 checkNode.parent.indeterminate 这个没有被设置为true;下面打个补丁。


```js

const editRole = async (row: any) => {

 const { permissionIds} = await detailApi({ id: row.id })

 await nextTick()

  setCheckedKeys(permissionIds)  // 返回用户的权限id后,根据id选中树节点


 permissionIds.forEach((id:any) => {

   const nodeData = treeRef.value!.getNode(id)  // 根据权限id,获取每个选中的树节点

   console.log('nodeData',nodeData)

   console.log('nodeData.parent?.id',nodeData.parent?.id)

   // 反显,上面setCheckedKeys后,如果父级没有选中,则把半选状态设置true

   if(nodeData?.parent?.id != 0 &&  !nodeData?.parent?.checked){

     nodeData.parent.indeterminate = true

   }

 });

}

```


---


# 总结

后台管理系统常见的权限控制需求,这里讲button实现交互细节处理,

1. **取消选中**子级menu/button,父级不关联取消;

2. **选中/取消**父级catalog/menu,子级全部选中/取消;

3. **选中/取消**部分子级menu/button,父级关联半选中状态(indeterminate=true);

下篇再补上button 的根据权限控制显示,用vue3 的指令实现,谢谢关注

相关文章
|
2月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
562 139
|
2月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
263 1
|
3月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
424 11
|
2月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
294 0
|
4月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
479 1
|
3月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
336 2
|
2月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
316 137
|
6月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
822 0
|
6月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
7月前
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
913 77

热门文章

最新文章