vue2实现一个树型控件(支持展开树与checkbox勾选)

news/2024/5/14 13:36:45/文章来源:https://blog.csdn.net/weixin_43845137/article/details/132026080

目录

  • vue2实现一个树型控件(支持展开树与checkbox勾选)
    • TreeItem.vue
    • Tree.vue
    • 效果

vue2实现一个树型控件(支持展开树与checkbox勾选)

TreeItem.vue

<template><div class="tree-item"><span @click="toggleExpanded" class="icon" v-show="treeNode && treeNode.children && treeNode.children.length"><spanclass="triangle":class="[ expanded ? 'triangle_down' : 'triangle_up']"></span></span><span class="icon-font icon-kaiwenjianjia-shense icon-wenjianjia"></span><span @click="toggleExpanded">{{ treeNode.deptName }}</span><input class="check-item check-style" type="checkbox" v-model="treeNode.checked" @change="handleChange(treeNode)"><div class="children" v-show="expanded"><TreeItem v-for="childNode in treeNode.children" :key="childNode.id" :tree-node="childNode" @checkItem="handleChange"></TreeItem></div></div>
</template><script>
export default {name: 'TreeItem',props: {// 每一项的节点数据treeNode: {type: Object,required: true}},data() {return {// 是否展开expanded: false,};},methods: {toggleExpanded() {this.expanded = !this.expanded;},handleChange(item) {console.log('handleChange',item, "treeNode",this.treeNode);this.setChecked(item,item.checked);this.$emit('checkItem',item)},// 递归 当父集选中或者取消 联动子集setChecked(node, checked) {node.checked = checked;if (node.children && node.children.length > 0) {for (let child of node.children) {this.setChecked(child, checked);}}}}
};
</script><style lang="less" scoped>
.tree-item {position: relative;font-size: 14px;.check-item {position: absolute;top: 10px;right: 4px;z-index: 111;cursor: pointer;}
}
.icon {width: 16px;display: inline-block;margin-right: 4px;line-height: 20px;cursor: pointer;
}
.icon-wenjianjia {color: #ccc;margin-right: 6px;
}
.children {margin-left: 20px;
}
input[type="checkbox"] {/* 未选中时的样式 */appearance: none;border: 1px solid transparent;width: 14px;height: 14px;display: inline-block;position: relative;vertical-align: middle;cursor: pointer;background-color: #eee;
}/* 选中时的样式 */
input[type="checkbox"]:checked {background-color: #1bc5bd;
}/* ✔图标 */
input[type="checkbox"]:checked:after {content: "✔";position: absolute;left: 1px;top: -11px;font-size: 12px;color: #fff;
}
.triangle {position: relative;top: -4px;transition: 0.5s;
}
.triangle_up {display: inline-block;margin: 0px;width: 0px;height: 0px;border-left: 4px solid transparent;border-right: 4px solid transparent;border-bottom: 4px solid #ccc;
}
.triangle_down {display: inline-block;margin: 0px;width: 0px;height: 0px;border-left: 4px solid transparent;border-right: 4px solid transparent;border-top: 4px solid #ccc;
}
</style>

Tree.vue

<template><div class="select-tree-com"><TreeItemclass="tree-item" v-for="treeNode in treeData" :key="treeNode.id" :tree-node="treeNode"@checkItem="checkItem"></TreeItem></div>
</template><script>
import TreeItem from "./TreeItem"
export default {name:'SelectTreeCom',components:{TreeItem},props: {// 结构数据lists: {type: Array,default () {return []}},// 是否开启checkboxcheckbox: {type: Boolean,default: false},},data() {return {treeData: [{id: 1,name: 'Node 1',deptCode:1,deptName:'Node-1',checked: false,children: [{id: 11,deptCode:11,deptName:'Node-11',parentId: 1,name: 'Node 11',checked: false,children: [{id: 111,deptName:'Node-111',deptCode:111,parentId: 11,name: 'Node 111',checked: false,children: [{id: 1111,deptName:'Node-1111',deptCode:1111,parentId: 111,name: 'Node 1111',checked: false,children: []},{id: 1112,deptName:'Node-1112',deptCode:1112,parentId: 111,name: 'Node 1112',checked: false,children: []}]},{id: 112,deptName:'Node-112',deptCode:112,parentId: 11,name: 'Node 112',checked: false,children: []}]},{id: 12,deptName:'Node-12',deptCode:12,parentId: 1,name: 'Node 12',checked: false,children: []},{id: 13,deptName:'Node-13',deptCode:13,parentId: 1,name: 'Node 13',checked: false,children: [{id: 131,deptName:'Node-131',deptCode:131,parentId: 13,name: 'Node 131',checked: false,children: [{id: 1311,deptName:'Node-1311',deptCode:1311,parentId: 131,name: 'Node 1311',checked: false,children: []},{id: 1312,deptName:'Node-1312',deptCode:1312,parentId: 131,name: 'Node 1312',checked: false,children: []}]},{id: 132,deptName:'Node-132',deptCode:132,parentId: 13,name: 'Node 132',checked: false,children: []}]},]},{id:2,deptName:'Node-2',deptCode:2,name: 'Node 2',checked: false,children: []}],// treeData: [],// 选中的所有项 check为truecheckList:[],};},watch:{lists:{handler(newV){console.log('selectTreeeCom组件lists',newV);// this.treeData = [...newV]},// immediate: true}},created() {},methods: {// 拿到当前选中的所有item数据checkItem(item) {// console.log('selectcom-checkItem',item);let newArr = []newArr = this.flattenNodes(item)console.log('newArr',newArr);// 存储选中的!newArr && newArr.length && newArr.forEach(item => {if ( item.checked ) {this.checkList.push(item)}});console.log('存储选中的-this.checkList',this.checkList);// 处理再一次选中时 包含之前的选项,覆盖之前的选项 checkthis.checkList && this.checkList.length && this.checkList.forEach(itemB =>{newArr.some(itemA => {if ( itemA.id === itemB.id ) {itemB.checked = itemA.checked}})})console.log('处理this.checkList',this.checkList);// 过滤掉 check为false 得到实际选中的数据this.checkList = this.checkList.filter(item=>{if(item.checked) {return item;}})// console.log('res-this.checkList',this.checkList);// 去重let uniqueArr = []uniqueArr = Array.from(new Set(this.checkList.map(item => item.id))).map(id => this.checkList.find(item => item.id === id));console.log('uniqueArr',uniqueArr);this.$emit('getCheckList', uniqueArr)},// 把树对象 扁平化为父+子的数据flattenNodes(data) {let nodes = [];// 添加当前节点到结果数组中nodes.push({id: data.id,name: data.name,checked: data.checked,deptCode: data.deptCode,deptName: data.deptName});// 遍历子级节点并递归处理if (data.children && data.children.length > 0) {for (let child of data.children) {nodes = nodes.concat(this.flattenNodes(child));}}return nodes;},// 全选setCheckAll(params){// console.log('setCheckAll',params);const allTreeData = this.treeToOneArr(this.treeData)if ( params ) {this.checkList = [...allTreeData]return this.checkList} else {this.checkList = []return this.checkList}},// 取消全选cancelCheckAll(){this.checkList = []},// tree数据 扁平化treeToOneArr(arr) {const data = JSON.parse(JSON.stringify(arr))const newData = []const hasChildren = item => {(item.children || (item.children = [])).map(v => {hasChildren(v)})delete item.childrennewData.push(item)}data.map(v => hasChildren(v))return newData},oneArrToTree(data) {// 对源数据深度克隆const cloneData = JSON.parse(JSON.stringify(data))// filter嵌套filter相当于for循环嵌套for循环const result = cloneData.filter(parent => {// 返回每一项的子级数组const branchArr = cloneData.filter(child => parent.parentCode === child.parentCode)// 若子级存在,则给子级排序;且,赋值给父级if (branchArr.length > 0) {branchArr.sort(this.compare('order'))parent.children = branchArr}// 返回最高的父级,即,parent_id为0,return parent.parentCode === '00'})// 给最高级的父级排序result.sort(this.compare('order'))return result},// 对象数组排序compare(property) {return function(a, b) {const value1 = a[property]const value2 = b[property]return value1 - value2// 升序,降序为value2 - value1}},}};
</script><style lang="less" scoped>
.select-tree-com {padding: 10px 0;
}
.tree-item {line-height: 34px;}
</style>

效果

在这里插入图片描述

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

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

相关文章

如何将论文中的字快速复制出来?图片如何提取文字?

在日常的办公中&#xff0c;我们经常会遇到需要将纸质文件里的文字提取出来&#xff0c;再转换为电子档的情况&#xff0c;如果我们采用手动输入的话&#xff0c;不仅速度太慢&#xff0c;而且还可能因此耽误到后边的工作&#xff0c;是不是已经有小伙伴遇到这种现象&#xff0…

Redis以及Java使用Redis

一、Redis的安装 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储&#xff0c;读写性能高 适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09; 企业应用广泛 官网&#xff1a;https://redis.io 中文网&#xff1a;https://www.redis.net.cn/ Redis…

mysql的日期类型的数据转换为年或者月类型的统计

SELECT CONCAT(YEAR(DATE), if (MONTH(DATE)<10,CONCAT(0,MONTH(DATE)),MONTH(DATE))) AS date , round(SUM(capacity),2) AS ca_dsoc FROM dianchi4 where date > 20211231 GROUP BY YEAR(DATE), MONTH(DATE) 月度的跨年处理就是第一个

文本怎么用手机生成二维码?二维码在线文本码制作技巧

现在二维码可以展示的内容越来越丰富&#xff0c;比如文本就是很常见的一种形式。编辑好文本内容之后&#xff0c;将文字内容添加到二维码中&#xff0c;其他人扫码就可以获取到文字内容&#xff0c;那么文本二维码该如何制作呢&#xff1f;想要制作二维码&#xff0c;那么可以…

SpringCloud集成OpenTelemetry的实现

SpringCloud项目做链路追踪&#xff0c;比较常见的会集成SleuthZipKin来完成&#xff0c;但这次的需求要集成开源框架OpenTelemetry&#xff0c;这里整理下实现过程。相关文章&#xff1a; 【SpringCloud集成SleuthZipkin进行链路追踪】 【OpenTelemetry框架Trace部分整理】 …

百度地图点标记加调用

先看效果 PHP代码 <?phpnamespace kds_addons\edata\controller;use think\addons\Controller; use think\Db;class Maps extends Controller {// 经纬度计算面积function calculate_area($points){$totalArea 0;$numPoints count($points);if ($numPoints > 2) {f…

国企普通员工如何才能成为公务员,这三种途径可供参考

国企普通员工如何转变成公务员&#xff1f;作为国企普通员工&#xff0c;如果要成为国家公务员&#xff0c;其主要的路径有三个方面&#xff0c;一是符合国家公务员法规定的公务员招录条件要求的&#xff0c;可以报考国家公务员&#xff1b;二是在国有企业担任领导职务&#xf…

有趣的Python之基本语法(一篇足够)

目录 Python简介 基本数据类型 进入交互模式 input()函数 条件语句 逻辑运算符 列表list 元组 字典 循环语句 format()方法和f 定义函数 python中的标准库引入 引入第三方库模块 面向对象 读文件 写文件 异常处理 Python简介 面向对象编程、函数式编程和过程…

【rtmp】1: FLV videotag 转annexb

【FLV】AVC+AAC的FLV解析过程及pts、dts计算 反复多次,才能熟记细节。 明确细节,遇到问题才能解决。 rtmp 推送flv时, 首先解析flv,flv videotag 转annexb 格式。 然后 按照annexb 输入给rtmp,让rtmp 推送。 而rtmp 推送又需要把annexb 转为avcc 。 annexb 格式文件 录制的…

day58 单调栈

单调栈 使用场景&#xff1a;通常是一维数组&#xff0c;要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置 本质&#xff1a;空间换时间 三个判断条件&#xff1a; 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况 当前遍历的元素T[i]等于栈顶元素T[st.to…

网络安全学习笔记——burp和SqlMap的tips

一、Burp 爆破 1、Burp爆账号密码 burp爆破的前提条件——该网站账号密码没有进行加密而是明文&#xff0c;且验证码可以重复使用&#xff0c;如下图数据包中直接显示账号与密码且验证码不需要重复提交&#xff08;此处需要自己使用burp进行测试&#xff09; 1、进入burp&am…

树莓派通过天线+gps获取经纬度并调用高德地图api在地图上标点

完整项目为《基于机器视觉的行人和路面缺陷检测及其边缘设备部署》 完整功能视频演示地址&#xff1a;本科最后的课设&#xff1a;“车载系统的辅助系统——基于机器视觉的行人和路面缺陷检测”完结撒花*罒▽罒*_哔哩哔哩_bilibili 该博客介绍的功能为&#xff1a; 1&#xff1…

实例讲解:通过三个案例搞懂tcp的那些冷门知识

最近在做数据库相关的事情&#xff0c;碰到了很多TCP相关的问题&#xff0c;新的场景新的挑战&#xff0c;有很多之前并没有掌握透彻的点&#xff0c;大大开了一把眼界&#xff0c;选了几个案例分享一下。 案例一&#xff1a;TCP中并不是所有的RST都有效 背景知识 在TCP协议…

Selenium-用这个框架自动化任何你想做的事情!

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

JPEG有损图像压缩编码器(附源码)

概述 一个基本由自己实现的JPEG有损图像压缩编码器&#xff0c;基于JFIF&#xff08;JPEG文件交换格式&#xff09;标准&#xff1a; 色彩空间转换&#xff08;RGB to YUV&#xff09;色度抽样&#xff08;采样因子4:2:0&#xff09;MCU分块&#xff08;16x16的最小编码单元&…

开放麒麟1.0发布一个月后,到底怎么样?另一款操作系统引发热议

具有里程碑意义 7月5日&#xff0c;国产首个开源桌面操作系统“开放麒麟1.0”正式发布。 标志着我国拥有了操作系统组件自主选型、操作系统独立构建的能力&#xff0c;填补了我国在这一领域的空白。 举国欢庆&#xff0c;算的上是里程碑意义了&#xff01; 发布后用着如何&a…

【Python】PySpark 数据计算 ② ( RDD#flatMap 方法 | RDD#flatMap 语法 | 代码示例 )

文章目录 一、RDD#flatMap 方法1、RDD#flatMap 方法引入2、解除嵌套3、RDD#flatMap 语法说明 二、代码示例 - RDD#flatMap 方法 一、RDD#flatMap 方法 1、RDD#flatMap 方法引入 RDD#map 方法 可以 将 RDD 中的数据元素 逐个进行处理 , 处理的逻辑 需要用外部 通过 参数传入 map…

深入理解 SQL:从基本查询到高级聚合

目录 背景理论知识示例1211. 查询结果的质量和占比&#xff08;Round group by&#xff09;1204. 最后一个能进入巴士的人 &#xff08;Having limit order by&#xff09;1193. 每月交易 I&#xff08;if group by&#xff09;1179. 重新格式化部门表1174. 即时食物配送 II&am…

链表刷题常用技巧——快慢指针

强大&#xff0c;不动如山的强大&#xff0c;不会输给自己的真正的强大。 往期回顾&#xff1a; 数据结构——单链表 单链表力扣刷题 文章目录 经典例题&#xff1a;链表的中间结点 题目分析及双指针思路引入 双指针图解 leetcode 核心代码 判断环形链表——快慢指针…

基于SSM+JSP+LayUI的校园任务帮管理系统

校园帮项目 校园即时服务平台 用户角色 管理员 功能 登录、公告管理&#xff08;发布公告、停用公告&#xff09;、任务管理&#xff08;下架任务、删除任务&#xff09;、用户管理&#xff08;用户充值、限制用户&#xff09;、修改密码 用户角色 用户 功能 注册、登录…