如何实现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 相关文章推荐
如何正确解决VuePress本地访问出现资源报错404的问题
Dec 03 Vue.js
vue图片裁剪插件vue-cropper使用方法详解
Dec 16 Vue.js
vue 使用rules对表单字段进行校验的步骤
Dec 25 Vue.js
Vue实现简易购物车页面
Dec 30 Vue.js
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 Vue.js
vue实现验证用户名是否可用
Jan 20 Vue.js
vue实现拖拽进度条
Mar 01 Vue.js
vue 数据双向绑定的实现方法
Mar 04 Vue.js
浅谈Vue的computed计算属性
Mar 21 Vue.js
vue使用echarts实现折线图
Mar 21 Vue.js
vue+iview实现手机号分段输入框
Mar 25 Vue.js
Vue.Draggable实现交换位置
Apr 07 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
PHP的异常处理类Exception的使用及说明
2012/06/13 PHP
详解PHP中的状态模式编程
2015/08/11 PHP
PHP实现多图上传(结合uploadify插件)思路分析
2016/11/30 PHP
PHP实现打包zip并下载功能
2018/06/12 PHP
让插入到 innerHTML 中的 script 跑起来的实现代码
2006/07/01 Javascript
Javascript isArray 数组类型检测函数
2009/10/08 Javascript
JavaScript 直接操作本地文件的实现代码
2009/12/01 Javascript
JavaScript 模拟用户单击事件
2009/12/31 Javascript
js遍历td tr等html元素
2012/12/13 Javascript
浅析js中取绝对值的2种方法
2013/07/09 Javascript
js实现网页标题栏闪烁提示效果实例分析
2014/11/20 Javascript
浅谈jQuery中的事件
2015/03/23 Javascript
针对初学者的jQuery入门指南
2015/08/15 Javascript
BootStrap的弹出框(Popover)支持鼠标移到弹出层上弹窗层不隐藏的原因及解决办法
2016/04/03 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
详解关于vue2.0工程发布上线操作步骤
2018/09/27 Javascript
js时间戳转yyyy-MM-dd HH-mm-ss工具类详解
2019/04/30 Javascript
JS常用跨域方法实现原理解析
2020/12/09 Javascript
Python3读取UTF-8文件及统计文件行数的方法
2015/05/22 Python
Python lxml模块安装教程
2015/06/02 Python
python dataframe常见操作方法:实现取行、列、切片、统计特征值
2018/06/09 Python
使用 Python 实现简单的 switch/case 语句的方法
2018/09/17 Python
详解python的argpare和click模块小结
2019/03/31 Python
python制作图片缩略图
2019/04/30 Python
python flask搭建web应用教程
2019/11/19 Python
python matplotlib库的基本使用
2020/09/23 Python
python中uuid模块实例浅析
2020/12/29 Python
世界上最大的网络主机公司:1&1
2016/10/12 全球购物
开放系统互连参考模型
2016/06/29 面试题
竞选班干部演讲稿
2014/04/24 职场文书
宪法宣传周工作方案
2014/05/26 职场文书
责任书范本
2014/08/25 职场文书
2014年卫生保健工作总结
2014/12/08 职场文书
2016年父亲节寄语
2015/12/04 职场文书
初中政治教师教学反思
2016/02/23 职场文书
vue+element ui实现锚点定位
2021/06/29 Vue.js