如何实现vue的tree组件


Posted in Vue.js onDecember 03, 2020

前言

Tree一直是大家熟知的组件,做一些大型的后台管理系统都会用到。使用树组件可以完整的展现其中的层级关系,并具有展开收起选择等交互功能。

效果

如何实现vue的tree组件

节点可以无限的递归延伸
可以展开和收起子节点
如果子节点全部选择对应的父节点也应该选中,反之父节点取消选中对应子节点也需要取消选中

API

prop传递data属性,来描述所有的节点的信息

如何实现vue的tree组件

每个节点的配置描述如下

  • title: 展示的标题
  • expand 是否展开节点
  • checked 是否选中节点
  • children 子节点

以及还有两个event

  • on-toggle-expand 展开和收起子列表时触发的
  • on-check-change 点击checkbox触发

我们来 init tree主组件

首先需要考虑一个问题因为tree是递归遍历的,因为我们需要创建一个入口组件还有一个递归children的组件。

首先创建我们的tree组件

如何实现vue的tree组件

如何实现vue的tree组件

我们在初始化以及watch监听的时候重新深拷贝了一下prop传来的data并赋值给了cloneData

然后在template里来引入node.vue,然后循环cloneData来循环node.vue。node.vue接受两个prop

showCheckbox 就是tree组件接收的 showCheckbox 这里传给node组件来判断展示
data 为item 是一个object 负责渲染当前节点,如果当前节点有children 那就递归调用本身来递归渲染
这是使用了一个deepCopy的方法,这个是深拷贝的简单实现,递归的去重新重新赋值data数组,开辟新的堆内存与传入的数据无关联。不会破坏原有的数据

我们来 init node递归组件

node组件为主要组件,主要功能是展示当前项的title 以及 如果有children时递归本身。

  • 展开关闭按钮
  • checkbox
  • 节点的title
  • 递归

node的基本构造

如何实现vue的tree组件

prop中的data就是当前节点的所有信息,比如说是否展开和关闭当前的节点,是否选中,title标题以及children的子节点数组。

  • expand 判断条件为 data.children &&  data.children.length 才会展示 + 或者 - 按钮
  • checkbox就是当前的节点是否需要默认勾选

点击 + 号时会展开当前的子节点,点击 - 号会关闭,这一步只需要在handleExpand 中修改data的expand数据即可同时我们还需要触发一个emit来提示用户展示或者收起了节点

如何实现vue的tree组件

如何实现vue的tree组件

这里有一点需要注意 修改data.expand我们通过 VUE的 $set 并没有像下面这样

this.data.expand = !this.data.expand;

这里有什么区别呢?如果直接用上面的代码进行修改,就会发现数据虽然被修改了,但是视图没有被更新,这是因为这里的this.data 时props通过上一级传递出来的,也有可能时node递归传递的,无论如何咱们需要的cloneData里的节点数据,此时不一定初始化定义时就含有expand或者checked字段 如果不含有直接通过this.data.expand修改,这个expand时不可响应式的数据,所以视图不会被更新,干脆就直接用$set来改变

接下来我们就需要处理响应状态了,大家可能觉得不就是选中和取消吗 的确这样可以,但是树组件时有上下级关系,他们分为两种逻辑,当选中(或取消选中)一个节点时

  • 它下面的所有子节点都会被选中
  • 如果同一级所有子节点选中时,它的父级也自动选中,一直递归判断到根节点。

第 1 个逻辑相对简单,当选中一个节点时,只要递归地遍历它下面所属的所有子节点数据,修改所有的 checked 字段即可

如何实现vue的tree组件

再来看第2个逻辑 一个节点,除了手动选中(或反选),还有就是第 2 种逻辑的被动选中(或反选),也就是说,如果这个节点的所有直属子节点(就是它的第一级子节点)都选中(或反选)时,这个节点就自动被选中(或反选),递归地,可以一级一级响应上去。有了这个思路,我们就可以通过 watch 来监听当前节点的子节点是否都选中,进而修改当前的 checked 字段:

如何实现vue的tree组件

在 watch 中,监听了 data.children 的改变,并且是深度监听的。这段代码的意思是,当 data.children 中的数据的某个字段发生变化时(这里当然是指 checked 字段),也就是说它的某个子节点被选中(或反选)了,这时执行绑定的句柄 handler 中的逻辑。const checkedAll = !data.some(item => !item.checked); 也是一个巧妙的缩写,checkedAll 最终返回结果就是当前子节点是否都被选中了。

这里非常巧妙地利用了递归的特性,因为 node.vue 是一个递归组件,那每一个组件里都会有 watch 监听 data.children,要知道,当前的节点有两个”身份“,它既是下属节点的父节点,同时也是上级节点的子节点,它作为下属节点的父节点被修改的同时,也会触发上级节点中的 watch 监听函数。这就是递归。

结语

递归的可以把一个大问题通过不断调用自身的方式,使代码简洁的实现功能,但是个别问题像算法中斐波那契数列如果使用递归就会使得时间复杂度以及空间复杂度会飙升。总的来说要合理运用,活学活用。

以上就是如何实现vue的tree组件的详细内容,更多关于vue tree组件的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
vue开发chrome插件,实现获取界面数据和保存到数据库功能
Dec 01 Vue.js
如何实现vue的tree组件
Dec 03 Vue.js
vue3.0实现插件封装
Dec 14 Vue.js
Vue实现省市区三级联动
Dec 27 Vue.js
vue实现倒计时功能
Mar 24 Vue.js
vue中三级导航的菜单权限控制
Mar 31 Vue.js
Vue+Element UI实现概要小弹窗的全过程
May 30 Vue.js
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 Vue.js
vue中div禁止点击事件的实现
Apr 02 Vue.js
vue3.0 数字翻牌组件的使用方法详解
Apr 20 Vue.js
解决vue自定义组件@click点击失效问题
Apr 30 Vue.js
vue实现input输入模糊查询的三种方式
Aug 14 Vue.js
Vue实现图书管理小案例
Dec 03 #Vue.js
Vue router安装及使用方法解析
Dec 02 #Vue.js
vue3.0中setup使用(两种用法)
Dec 02 #Vue.js
vue3.0+vue-router+element-plus初实践
Dec 02 #Vue.js
Vue router传递参数并解决刷新页面参数丢失问题
Dec 02 #Vue.js
详解Vue3 Teleport 的实践及原理
Dec 02 #Vue.js
vue $router和$route的区别详解
Dec 02 #Vue.js
You might like
业余方法DIY电子管FM收音机
2021/03/02 无线电
php读取数据库信息的几种方法
2008/05/24 PHP
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
php数组函数序列之asort() - 对数组的元素值进行升序排序,保持索引关系
2011/11/02 PHP
php缓存技术详细总结
2013/08/07 PHP
一个简单安全的PHP验证码类 附调用方法
2016/06/24 PHP
php curl中gzip的压缩性能测试实例分析
2016/11/08 PHP
phpstudy的php版本自由修改的方法
2017/10/18 PHP
javascript使用isNaN()函数判断变量是否为数字
2013/09/21 Javascript
深入理解JavaScript是如何实现继承的
2013/12/12 Javascript
JQuery判断HTML元素是否存在的两种解决方法
2013/12/26 Javascript
自己使用js/jquery写的一个定制对话框控件
2014/05/02 Javascript
js使用心得分享
2015/01/13 Javascript
基于socket.io+express实现多房间聊天
2016/03/17 Javascript
深入理解setTimeout函数和setInterval函数
2016/05/20 Javascript
详解nodejs通过响应回写的方式渲染页面资源
2018/04/07 NodeJs
js删除指定位置超链接中含有百度与360的标题
2021/01/06 Javascript
[01:00:53]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Secret
2018/03/30 DOTA
[51:53]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第二场 11.01
2020/11/02 DOTA
pygame学习笔记(1):矩形、圆型画图实例
2015/04/15 Python
python定向爬取淘宝商品价格
2018/02/27 Python
Python之list对应元素求和的方法
2018/06/28 Python
Python检测数据类型的方法总结
2019/05/20 Python
详解PANDAS 数据合并与重塑(join/merge篇)
2019/07/09 Python
Python for循环与getitem的关系详解
2020/01/02 Python
Django {{ MEDIA_URL }}无法显示图片的解决方式
2020/04/07 Python
Python获取浏览器窗口句柄过程解析
2020/07/25 Python
Python使用pickle进行序列化和反序列化的示例代码
2020/09/22 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
2021/02/05 Python
美国祛痘、抗衰老药妆品牌:Murad
2016/08/27 全球购物
社区党务公开实施方案
2014/03/18 职场文书
个人委托书怎么写
2014/04/04 职场文书
音乐幼师求职信
2014/07/09 职场文书
反洗钱宣传活动总结
2014/08/26 职场文书
为什么代码规范要求SQL语句不要过多的join
2021/06/23 MySQL
5人制售《绝地求生》游戏外挂获利500多万元 被判刑
2022/03/31 其他游戏