解决 Vue3 + Element Plus 树形表格全选多选以及子节点勾选的问题

原文链接: 解决 Vue3 + Element Plus 树形表格全选多选以及子节点勾选的问题

前言

最近用到了 Element Plus 组件库的中的树形表格,但官网例子只能做到一层勾选,不能做到多层勾选,无法满足业务需求,所以研究了下,如何在子节点选满的情况下自动勾选上父节点? 勾选父节点时自动勾上全部子节点?

效果

从图中可看出,已支持父子节点联动,最后勾选的行数据保存在 multipleDevCreateList

代码

<el-table ref="multipleDevCreateRef" v-model:selected-row-keys="multipleDevCreateList" :data="tableData"style="width: 100%" row-key="Path" default-expand-all @select="select" @select-all="selectAll"@selection-change="handleSelectionChange" :tree-props="{ children: 'Children' }":row-class-name="tableRowClassName"><el-table-column type="selection" width="55" :selectable="selectable" /><el-table-column property="Path" label="设备名" width="240" /><el-table-column property="TypStr" label="类型" /><el-table-column property="Mount" label="挂载点" /><el-table-column property="Capacity" label="容量" />
</el-table>
interface nodeItem {Path: string //路径Capacity: string // 空间Parent: string // 父节点(如果空就是根节点)Mount: string  // 挂载点Typstr: string // 类型IsUsed: boolean // 是否使用Children?: nodeItem[]
}const multipleDevCreateRef = ref<InstanceType<typeof ElTable>>()
const multipleDevCreateList = ref<nodeItem[]>([])
const handleSelectionChange = (value: nodeItem[]) => {multipleDevCreateList.value = multipleDevCreateRef.value?.getSelectionRows()
}// 转化前数据:
/* [{"Capacity": "20.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdb","TypStr": "disk"},{"Capacity": "19.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdb","Path": "/dev/sdb1","TypStr": "part"},{"Capacity": "200.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdc","TypStr": "disk"},{"Capacity": "190.0GB","IsUsed": false,"Mount": "","Parent": "/dev/sdc","Path": "/dev/sdc1","TypStr": "part"},{"Capacity": "9.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdc","Path": "/dev/sdc2","TypStr": "part"},{"Capacity": "20.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdd","TypStr": "disk"},{"Capacity": "19.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdd","Path": "/dev/sdd1","TypStr": "part"}
] */
// 转化后的数据
const tableData = ref<any[]>([{"Capacity": "200.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdc","TypStr": "disk","Children": [{"Capacity": "190.GB","IsUsed": false,"Mount": "","Parent": "/dev/sdc","Path": "/dev/sdc1","TypStr": "part"},{"Capacity": "9.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdc","Path": "/dev/sdc2z","TypStr": "part"}]},{"Capacity": "20.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdd","TypStr": "disk","Children": [{"Capacity": "19.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdd","Path": "/dev/sdd1","TypStr": "part"}]},{"Capacity": "20.0GB","IsUsed": false,"Mount": "","Parent": "","Path": "/dev/sdb","TypStr": "disk","Children": [{"Capacity": "19.9GB","IsUsed": false,"Mount": "","Parent": "/dev/sdb","Path": "/dev/sdb1","TypStr": "part"}]}
])const tableRowClassName = ({ row }: { row: nodeItem }) => {// 被使用了的设备   颜色加深   原生UI 不太明显if (row.IsUsed === true) {return 'disabled-row'} else {return ''}
}const selectable = (row: nodeItem) => {return row.IsUsed === false
}const setChildren = (children: nodeItem[], type: boolean) => {// 编辑多个子层级children.map((j: nodeItem) => {toggleSelection(j, type)if (j.Children) {setChildren(j.Children, type)}})
}// 设置父级选中/取消
const setParent = (currentRow: any, type: boolean, parent: nodeItem[], selectionLists: nodeItem[]) => {if (!parent.length) {parent = tableData.value}let allSelect: any[] = []parent.forEach((item: nodeItem) => {if (item.Children) {// 注:Parent 是当前选中节点的所有父节点的一个字符串形式的数据,这个很关键if (currentRow.Parent === item.Path) {// 选中if (type) {selectionLists.forEach((k: nodeItem) => {item.Children?.forEach((j: nodeItem) => {if (k.Path == j.Path) {allSelect.push(j)}})})if (allSelect.length == item.Children.length) {toggleSelection(item, type)selectionLists.push(item)select(selectionLists, item)} else {setParent(currentRow, type, item.Children, selectionLists)}} else {// 取消选中toggleSelection(item, type)setParent(currentRow, type, item.Children, [])}}}})
}const toggleSelection = (row: nodeItem, select: boolean) => {// 编辑多个子层级if (row) {multipleDevCreateRef.value?.toggleRowSelection(row, select)}
}// 选中父节点时,子节点一起选中/取消
const select = (selection: nodeItem[], row: nodeItem) => {const hasSelect = selection.some((el: nodeItem) => {return row.Path === el.Path})if (hasSelect) {if (row.Children) {// 解决子组件没有被勾选到setChildren(row.Children, true)}// 子节点被全勾选,父节点也勾上setParent(row, true, [], selection)} else {if (row.Children) {setChildren(row.Children, false)}// 子级取消选中, 传入当前选中节点, 所有父级取消选中setParent(row, false, [], [])}
}// 选择全部
const selectAll = (selection: nodeItem[]) => {// tabledata第一层只要有在selection里面就是全选const isSelect = selection.some((el: nodeItem) => {const tableDataPaths = tableData.value.map((j: nodeItem) => j.Path)return tableDataPaths.includes(el.Path)})// tableDate第一层只要有不在selection里面就是全不选const isCancel = !tableData.value.every((el: nodeItem) => {const selectPaths = selection.map(j => j.Path)return selectPaths.includes(el.Path)})if (isCancel) {tableData.value.map((el: nodeItem) => {if (el.Children) {// 解决子组件没有被勾选到setChildren(el.Children, false)}})}if (isSelect) {selection.map(el => {if (el.Children) {// 解决子组件没有被勾选到setChildren(el.Children, true)}})}
}

结语

应该没什么 bug ,遇到 bug 记得留言!

6289ec15a6149.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/145667.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app 小宠物 - 会说话的小鸟

在 template 中 <view class"container"><view class"external-shape"><view class"face-box"><view class"eye-box eye-left"><view class"eyeball-box eyeball-left"><span class"…

腾讯云创建了jenkins容器,但无法访问

1、首先&#xff0c;查看本机能不能ping通你的腾讯云服务器 如果ping的通那就下一步 2、查看腾讯云服务器的防火墙关了没&#xff0c;没关关掉、 firewall-cmd --state not running 3、那就在云服务器的控制台开放端口

手写SVG图片

有时候QT中可能会需要一些简单的SVG图片,但是网上的质量参差不齐,想要满意的SVG图片,我们可以尝试直接手写的方法. 新建文本文档,将以下代码复制进去,修改后缀名为.svg,保存 <?xml version"1.0" encoding"utf-8"?> <svg xmlns"http://www…

C#冒泡排序算法

冒泡排序实现原理 冒泡排序是一种简单的排序算法&#xff0c;其原理如下&#xff1a; 从待排序的数组的第一个元素开始&#xff0c;依次比较相邻的两个元素。 如果前面的元素大于后面的元素&#xff08;升序排序&#xff09;&#xff0c;则交换这两个元素的位置&#xff0c;使…

关于AES加密输出密文不为128位的倍数的原因

今天尝试用AES-256-OFB加密一个flag结果输出的密文是43字节&#xff0c;不是128位&#xff08;16字节&#xff09;的倍数&#xff0c;代码如下&#xff1a; import os from Crypto.Cipher import AES databflag{a7ba7128-3917-4551-8260-b3499e9dd7b12} aes AES.new(os.urand…

如何进行高效的代码审查

代码审查是软件开发过程中至关重要的一环。它是指由开发团队中的其他成员对代码进行检查&#xff0c;以确保代码的质量和一致性。 代码审查可以帮助发现潜在的问题&#xff0c;例如内存泄漏、安全漏洞或性能问题。通过及早发现这些问题&#xff0c;可以避免它们在后期的软件开…

初识测开/测试

前言 在进入软件测试的正式讲解之前&#xff0c;我们需要对这个行业有一个整体的了解。 当我们从软件开发转向软件测试的时候&#xff0c;多数公司是欢迎的&#xff0c;而且难度也小。 反之&#xff0c;当我们从软件测试转向软件开发的时候&#xff0c;难度将会变得很大。 关于…

驱动作业10.23

现象 test.c #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include "head.h"in…

微信小程序一键获取位置

需求 有个表单需要一键获取对应位置 并显示出来效果如下&#xff1a; 点击一键获取获取对应位置 显示在 picker 默认选中 前端 代码如下: <view class"box_7 {{ showChange1? change-style: }}"><view class"box_11"><view class"…

物联网_00_物理网介绍

1.物联网为什么会出现? 一句话-----追求更高品质的生活, 随着科技大爆炸, 人类当然会越来越追求衣来伸手饭来张口的懒惰高品质生活, 最早的物联网设备可以追溯到19世纪末的"在线可乐售卖机"和"特洛伊咖啡壶"(懒惰的技术人员为了能够实时看到物品的情况而设…

SSM - Springboot - MyBatis-Plus 全栈体系(三十五)

第八章 项目实战 四、后台功能开发 2. 首页模块开发 2.1 查询首页分类 2.1.1 需求描述 进入新闻首页,查询所有分类并动态展示新闻类别栏位 2.1.2 接口描述 url 地址&#xff1a;portal/findAllTypes 请求方式&#xff1a;get 请求参数&#xff1a;无 响应数据&#xff…

漏洞复现--金和OASQL注入

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…