Element@2.15.14-tree checkStrictly 状态实现父项联动子项,实现节点自定义编辑、新增、删除功能

背景:现在有一个新需求,需要借助树结构来实现词库的分类管理,树的节点是不同的分类,不同的分类可以有自己的词库,所以父子节点是互不影响的;同样为了选择的方便性,提出了新需求,选择了父级子级需要全选,父级取消勾选子级需要全部取消勾选;分类支持修改名称、增加子节点、删除子节点,多选子节点时需要获取当前所选分类下的所有词库。
一、开发前需要知道的
1、树结构需要借助 element 的 tree 组件
2、树结构需要设置父子级不关联,即 :check-strictly="true"
3、节点选择时如果是非叶子结点(最后一层的子节点,没有 children),需要递归获取子节点,如果进行节点的选择与取消选择
4、自定义节点需要通过 slot 方式活着 render-content 方式实现
二、实现流程
1、引入 tree,传入源数据 data、设置 key,设置默认配置属性 defaultProps
1. 定义 tree
<el-tree:check-strictly="true":data="data"@check-change="checkChange"ref="treeRef"show-checkboxdefault-expand-allnode-key="id"ref="tree"highlight-current:props="defaultProps"
>
</el-tree>
2. 设置 data
data = [{id: xx, label: xx, children: {id: number, label: string, children: []}[]}]
3. 设置父子不关联
:check-strictly="true"
4. 设置默认配置
const defaultProps = {children: "children",label: "label",
}
2、实现父子勾选子级联动
// 1. 给 el-tree 绑定 check-change 事情
@check-change="checkChange"// 2. 实现 checkChange 函数
// data:当前节点 checked:节点是否选中 indeterminate:是否有选中的子项
function checkChange(data, checked, indeterminate) {console.log("data, checked, indeterminate", data, checked, indeterminate);this.$nextTick(() => {// 2.1 获取节点详细信息const nodeInfo = this.$refs.treeRef.getNode(data.id);const { isLeaf, checked } = nodeInfo;this.nodeInfo = nodeInfo;function getAllIds(arr, res = []) {for (let i = 0; i < arr.length; i++) {res.push(arr[i].id);if (arr[i].children && arr[i].children.length) {getAllIds(arr[i].children, res);}}return res;}// 2.2 获取当前已选中的节点console.log(this.$refs.treeRef.getCheckedKeys());// 2.3 如果是父级,子级选中跟取消选择if (!isLeaf) {const checkedIds = this.$refs.treeRef.getCheckedKeys();const ids = getAllIds(nodeInfo.data.children);console.log(ids);// 2.3.1 父级选中,子级全选if (checked) {this.$refs.treeRef.setCheckedKeys(Array.from(new Set([...checkedIds, ...ids])));} else {// 2.3.2 父级取消选中,子级全不选this.$refs.treeRef.setCheckedKeys(Array.from(new Set(checkedIds.filter((item) => !ids.includes(item)))));}}});
},
3、通过 slot 实现编辑、新增、删除
1. slot 内容
<span class="custom-tree-node" slot-scope="{ node, data }"><span>{{ node.label }}</span><span><el-button type="text" size="mini" @click="() => edit(node, data)">edit</el-button><el-button type="text" size="mini" @click="() => append(data)">Append</el-button><el-buttontype="text"size="mini"@click="() => remove(node, data)">Delete</el-button></span>
</span>2. 设置函数
{// 2.1 编辑,子级可以弹窗回显名称,然后修改名称edit(node, data) {console.log(node, data);},// 2.2 新增,新增内容自己定,也可以弹窗自定义名称,通过接口返回 id 再拼接append(data) {const newChild = { id: this.id++, label: "testtest", children: [] };if (!data.children) {this.$set(data, "children", []);}data.children.push(newChild);},// 2.3 删除,可以先进行提示,提示确定后再删remove(node, data) {const parent = node.parent;const children = parent.data.children || parent.data;const index = children.findIndex((d) => d.id === data.id);children.splice(index, 1);}
}
三、整体代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><linkrel="stylesheet"href="https://unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css"/><style>.custom-tree-node {flex: 1;display: flex;align-items: center;justify-content: space-between;font-size: 14px;padding-right: 8px;}</style></head><body><script src="https://unpkg.com/vue@2.7.16/dist/vue.js"></script><script src="https://unpkg.com/element-ui@2.15.14/lib/index.js"></script><div id="app"><el-tree:check-strictly="true":data="data"@check-change="checkChange"ref="treeRef"show-checkboxdefault-expand-allnode-key="id"ref="tree"highlight-current:props="defaultProps"><span class="custom-tree-node" slot-scope="{ node, data }"><span>{{ node.label }}</span><span><el-button type="text" size="mini" @click="() => edit(node, data)">edit</el-button><el-button type="text" size="mini" @click="() => append(data)">Append</el-button><el-buttontype="text"size="mini"@click="() => remove(node, data)">Delete</el-button></span></span></el-tree><div class="buttons"><el-button @click="getCheckedNodes">通过 node 获取</el-button><el-button @click="getCheckedKeys">通过 key 获取</el-button><el-button @click="setCheckedNodes">通过 node 设置</el-button><el-button @click="setCheckedKeys">通过 key 设置</el-button><el-button @click="resetChecked">清空</el-button></div></div><script>var Main = {methods: {edit(node, data) {console.log(node, data);},append(data) {const newChild = { id: this.id++, label: "testtest", children: [] };if (!data.children) {this.$set(data, "children", []);}data.children.push(newChild);},remove(node, data) {const parent = node.parent;const children = parent.data.children || parent.data;const index = children.findIndex((d) => d.id === data.id);children.splice(index, 1);},checkChange(data, checked, indeterminate) {this.node = data;this.checked = checked;this.indeterminate = indeterminate;// console.log("data, checked, indeterminate", data, checked, indeterminate);this.$nextTick(() => {console.log(data.id);const nodeInfo = this.$refs.treeRef.getNode(data.id);const { isLeaf, checked } = nodeInfo;this.nodeInfo = nodeInfo;console.log(nodeInfo);// console.log(// "nodeInfo, isLeaf, childNodes, checked",// nodeInfo,// isLeaf,// childNodes,// checked// );function getAllIds(arr, res = []) {for (let i = 0; i < arr.length; i++) {res.push(arr[i].id);if (arr[i].children && arr[i].children.length) {getAllIds(arr[i].children, res);}}return res;}console.log(this.$refs.treeRef.getCheckedKeys());if (!isLeaf) {const checkedIds = this.$refs.treeRef.getCheckedKeys();const ids = getAllIds(nodeInfo.data.children);console.log(ids);if (checked) {this.$refs.treeRef.setCheckedKeys(Array.from(new Set([...checkedIds, ...ids])));} else {this.$refs.treeRef.setCheckedKeys(Array.from(new Set(checkedIds.filter((item) => !ids.includes(item)))));}}});},getCheckedNodes() {console.log(this.$refs.tree.getCheckedNodes());},getCheckedKeys() {console.log(this.$refs.tree.getCheckedKeys());},setCheckedNodes() {this.$refs.tree.setCheckedNodes([{id: 5,label: "二级 2-1",},{id: 9,label: "三级 1-1-1",},]);},setCheckedKeys() {this.$refs.tree.setCheckedKeys([3]);},resetChecked() {this.$refs.tree.setCheckedKeys([]);},},data() {return {id: 10,data: [{id: 1,label: "一级 1",children: [{id: 4,label: "二级 1-1",children: [{id: 9,label: "三级 1-1-1",},{id: 10,label: "三级 1-1-2",},],},],},{id: 2,label: "一级 2",children: [{id: 5,label: "二级 2-1",},{id: 6,label: "二级 2-2",},],},{id: 3,label: "一级 3",children: [{id: 7,label: "二级 3-1",},{id: 8,label: "二级 3-2",},],},],defaultProps: {children: "children",label: "label",},};},};var Ctor = Vue.extend(Main);new Ctor().$mount("#app");</script></body>
</html>
四、codepen 在线编辑
https://codepen.io/CAILeiz/pen/MYgpYOW
相关文章:
Element@2.15.14-tree checkStrictly 状态实现父项联动子项,实现节点自定义编辑、新增、删除功能
背景:现在有一个新需求,需要借助树结构来实现词库的分类管理,树的节点是不同的分类,不同的分类可以有自己的词库,所以父子节点是互不影响的;同样为了选择的方便性,提出了新需求,选择…...
详细介绍如何使用rapidjson读取json文件
本文主要详细介绍如何使用rapidjson库来实现.json文件的读取,分为相关基础介绍、结合简单示例进行基础介绍、结合复杂示例进行详细的函数实现介绍等三部分。 一、相关基础 1、Json文件中的{} 和 [] 在 JSON 文件中,{} 和 [] 分别表示不同的数据结构&…...
【Qt】显示类控件:QLabel、QLCDNumber、QProgressBar、QCalendarWidget
目录 QLabel QFrame 例子: textFormat pixmap、scaledContents alignment wordWrap、indent、margin buddy QLCDNumber 例子: QTimer QProgressBar 例子: QCalendarWidget 例子: QLabel 标签控件,用来显示…...
设计模式-访问者设计模式
介绍 访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变个元素的类的前提下定义作用于这些元素的新操作。 问题:在一个机构里面有两种员工,1.Teacher 2.Engineer 员…...
Spring框架IOC
目录 一、Spring框架的介绍 1.1 Spring框架的概述 1.2 Spring框架的优点 二、Spring的核心 IOC技术 2.1 什么是IOC 2.2 IOC的程序入门 2.3 IOC技术总结 2.4 Spring框架的Bean管理的配置文件方式 一、Spring框架的介绍 1.1 Spring框架的概述 Spring是一个开放源代码的…...
有哪些免费的 ERP 软件可供选择?哪些 ERP 软件使用体验较好?
想找个 “免费” 的 ERP 软件? 咱得知道,ERP 那可是涉及财务、人力、供应链、采购、销售等好多方面的重要企业软件。功能这么全,能免费才怪呢!真要是有免费的,早就火遍大江南北,说不定把市场都垄断了&…...
思科CCNA认证都学什么考什么?
关注 工 仲 好:IT运维大本营CCNA考试要学的东西很多,你不要看它只是一个初级认证,但是它的专业内容知识是不少的,你想要学好也是需要下一番苦功的。 那么考CCNA需要学哪些东西呢?下面我们就来了解一下吧。 01、考CCN…...
模型部署学习笔记——模型部署关键知识点总结
模型部署学习笔记——模型部署关键知识点总结 模型部署学习笔记——模型部署关键知识点总结1. CUDA中Grid和Block的定义是什么?Shared Memory的定义?Bank Conflict的定义?Stream和Event的定义?2. TensorRT的工作流程?3…...
22智能 狄克斯特拉算法复习
狄克斯特拉算法 图 根据边有无方向分为: 有向图、无向图 根据边有无权重变量分为: 有权图、无权图 根据顶点是否连通分为: 连通图和非连通图入度:表示有多少条边指向该顶点出度:表示有多少条边从该顶点指出算法步骤&a…...
首个!艾灵参编的工业边缘计算国家标准正式发布
近日,艾灵参与编制的《面向工业应用的边缘计算 应用指南》(以下简称《标准》)国家标准正式发布,将于2025年5月1日起实施。这一里程碑式的成果,不仅标志着我国在工业边缘计算技术标准化领域取得了重大突破,成…...
curl也支持断点续传
curl断点续传 访问外网资源,特别是Github上比较大的资源,例如,笔者遇到的calico发布包,经常会遇到在浏览器上下载半途中断。 那么支持断点续传的下载工具,就是应对这种情况的好帮手! 简单的断点续传工具…...
交换机链路聚合(手动负载分担模式)(eNSP)
目录 交换机SW_C配置: 交换机-PC划分vlan: 交换机-交换机端口聚合: 交换机SW_D配置: 交换机-PC划分vlan: 交换机-交换机端口聚合: 验证: 链路聚合的端口清除: 交换机端口聚合的存在意义主要有以下几点: 增加带宽 提高冗余性和可靠性 实现负载均衡 降低成本 …...
jmeter 接口性能测试 学习笔记
目录 说明工具准备工具配置jmeter 界面汉化配置汉化步骤汉化结果图 案例1:测试接口接口准备线程组添加线程组配置线程组值线程数(Number of Threads)Ramp-Up 时间(Ramp-Up Period)循环次数(Loop Count&…...
`HashMap`、`Hashtable` 和 `HashSet`的区别
HashMap、Hashtable 和 HashSet 都是 Java 中常用的集合类,它们的功能和实现有所不同,尽管它们都使用哈希表(hash table)作为底层数据结构。以下是它们之间的主要区别: 1. HashMap 和 Hashtable 的区别 特性HashMapH…...
Arduino中解析JSON数据
JSON JSON(JavaScript Object Notation,即JavaScript对象表示法)是一种广泛采用的开放标准文件格式与数据交换格式。它兼具人类可读性和机器易解析性,使得数据的编写、阅读、生成及解析都变得十分便捷。JSON的设计不依赖于特定编…...
linux----文件访问(c语言)
linux文件访问相关函数 打开文件函数 - open 函数原型:int open(const char *pathname, int flags, mode_t mode);参数说明: pathname:这是要打开的文件的路径名,可以是绝对路径或者相对路径。例如,"/home/user/…...
源码分析之Openlayers中MousePosition鼠标位置控件
概述 本文主要介绍 Openlayers 中的MousePosition鼠标位置控件,该控件会创建一个元素在页面的右上方用来实时显示鼠标光标的位置坐标。该控件在实际应用很有效,可以实时获取鼠标位置,但是一般控件元素都会自定义。 源码分析 MousePosition…...
以ATTCK为例构建网络安全知识图
ATT&CK(Adversarial Tactics, Techniques, and Common Knowledge )是一个攻击行为知识库和模型,主要应用于评估攻防能力覆盖、APT情报分析、威胁狩猎及攻击模拟等领域。本文简单介绍ATT&CK相关的背景概念,并探讨通过ATT&a…...
myexcel的使用
参考: (1)api文档:https://www.bookstack.cn/read/MyExcel-2.x/624d8ce73162300b.md (2)源代码: https://github.com/liaochong/myexcel/issues 我: (1)m…...
Unity 上好用的插件
PlayerMaker BehaviorDesigner Cinemachine Timeline Hybrid Addressable AssetBundle Blower Simple Zoom 大地图上缩放和平移使用ScrollRect的好效果实现...
别再乱接线了!手把手教你用SC-09电缆搞定三菱FX2N PLC通讯(附GX Developer配置)
三菱FX2N PLC通讯实战:SC-09电缆的正确打开方式 第一次接触三菱FX2N PLC时,很多人都会被通讯问题难住。那些看似简单的接线背后藏着不少门道——用错线序可能导致通讯失败,甚至损坏设备。本文将带你避开常见陷阱,从硬件连接到软件…...
避开勒让德函数那些坑:GRACE数据处理中MATLAB高效计算与调试技巧
GRACE数据处理中的勒让德函数实战:MATLAB高效计算与调试全指南 当你在深夜的实验室里盯着屏幕上那个不断报错的MATLAB脚本,勒让德函数的计算结果与文献数据相差了几个数量级,而论文截稿日期就在三天后——这种场景对处理GRACE球谐数据的研究者…...
STM32驱动PS2手柄控制智能小车实战(避坑指南+遥控代码解析)
STM32驱动PS2手柄控制智能小车实战(避坑指南遥控代码解析) 在创客社区和嵌入式开发领域,智能小车一直是验证硬件控制逻辑的理想平台。而将游戏手柄作为控制终端,不仅能让项目更具趣味性,还能深入理解工业级输入设备与嵌…...
TVBOX最新电视直播软件tv版下载与安装教程
如何安装最新版电视直播软件tv版TVBOX?先讲清楚:TVBox 是开源播放器,本身不带影视资源,装好后必须配置 “数据源 / 接口” 才能用。下面分「下载 → 安装 → 配置 → 常见问题」一步步来。(如果不会配置,可…...
OpenISP 模块拆解 · 第7讲:去马赛克 (CFA)
OpenISP 模块拆解 第7讲:去马赛克 (CFA) 模块作用 CFA 插值也叫 demosaic,是把单通道 Bayer RAW 转成三通道 RGB 的关键模块。每个传感器像素只采集 R/G/B 之一,CFA 要为每个位置估计缺失的两个颜色通道。 openISP 实现 源码类名为 CFA(img,…...
深入解析Keil MDK FLM算法:SRAM运行原理与下载机制
1. 项目概述:FLM算法,Keil MDK下载的“灵魂引擎”如果你用Keil MDK给一块新的APM32或者STM32芯片下载程序,点下那个“Download”或“Load”按钮,几秒钟后“Programming Done”的提示框弹出,这个过程看似简单࿰…...
某包丨图片+视频去水印去除工具
首先下载软件(工具在末尾),然后运行,自动打开网页如下: 接着打开某包,找到你要去除水印的图片或者视频的链接: 工具下载: 链接:https://pan.quark.cn/s/aec2cdde94ed...
VirtualBox虚拟机里Win10远程桌面黑屏?手把手教你改组策略搞定它
VirtualBox虚拟机Win10远程桌面黑屏终极解决方案:从策略组到网络优化的全链路排查 当你正沉浸在VirtualBox虚拟机的Windows 10环境中进行关键开发工作,突然发现远程桌面连接后只剩一片漆黑——这种体验就像在重要会议前突然失声。不同于物理机的远程连接…...
【物联网专业】案例9_2:控制数码管(定时器中断)
文章目录0 文章介绍1 仿真图2 效果图3 不完整代码4 思考题0 文章介绍 对应定时器/计数器案例目标的实现 用计数器中断0(P3^4)控制数码管段选 P1^6)控制数码位选 1 仿真图 2 效果图 3 不完整代码 复制该代码,其中有7个补充点&#…...
单频信号频谱检测仿真实验:从能量检测到匹配滤波器的性能对比
1. 项目概述:从“听”到“看”的信号世界 在无线通信、雷达探测、声学分析乃至医疗影像等众多领域,我们常常面对一个核心问题:如何从一段复杂的、充满噪声的波形中,准确地识别出一个特定频率的信号是否存在?这就像在一…...
