React实战 Tree组件简单实现

本文介绍了作者在熟悉React过程中实现Tree组件的过程,包括思路分析、具体实现和反思。组件采用维护数据结构和状态管理的方式,讨论了两种实现策略的优缺点,以及如何处理结点的全选、半选状态。文章旨在记录学习历程,分享组件设计经验。
摘要由CSDN通过智能技术生成

一、前言

  这个简单树组件也是自己为了熟悉react而做的,所以只是简单实现了基本功能,但是做完之后感觉其中也有很多需要自己总结的地方。其中还有几个未解决的问题自己在解决之后会修改这篇博文。话不多少,首先来看看我们到底要实现什么效果
在这里插入图片描述
我们的目标很简单,就是实现这样一个功能就行了,但是注意需要有一个半勾选的状态,就是父节点的某个子结点被选中了,那么这个结点就是半勾选状态。

二、思路分析

  当我们有了目标之后,就可以先整理一下整体思路。树组件的根本思想就是维护一个数据结构,然后通过这个数据结构来管理各个子结点的渲染。其中最为重要的也是它的选中/半选/未选状态的改变。因为你改变一个结点的状态后会影响到其他结点。那么,我们可以有一个实现树组件非常直观的思路:

  • 我给Tree组件传入一个完整的数据结构,类似下面这样:
[
	{
   
		name:"root", 
		children: [
			{
   
				name: "1", 
				children: [
					{
   
						name: "1-1", 
						children: []
					}
				]}
			{
   
				name: "2", 
				children: []
			}
		]
	}
]

  随后Tree组件利用这个数据结构自己将全部结点渲染出来。

  • 在每个结点上保存子节已被全选的个数和半选的个数,通过和children的长度进行比较,确定当前结点的状态。
  • 当一个结点被点击的时候,从头开始遍历整个数据结构,直到找到对应结点,同时,保存下找到结点经过的父节点。状态被影响了的结点就是这些父节点。

  这样,我们就能实现一个树组件的基本功能。但是,这样有下面几个问题:

  • 不易使用: 我们需要为tree组件传入一个完整的数据结构,当树很复杂时很难使用。
  • 数据结构是一个树形结构,树很深时遍历会存在性能问题
  • 每个结点的状态是由自己来判断的,我们应该有一个统一的机制,比如由父节点统一来判断各个子结点的状态,这样更加合理。
      自己在最初实现的时候就是依照这个思路进行实现的,最后也实现了基本效果。随后自己在网上参考了一个开源项目进行实现,对思路进行了调整。项目地址为: https://github.com/react-component/tree。 该项目有500多个start,所以应该还是有一定参考意义的。别问我为什么没有看antd的源码,问就是看不懂。

  所以,对思路进行调整之后,我们这样来实现一个树:

  • 使用Tree + TreeNode的方式来创建一个树,具体可以参考antd树组件的使用方式,那么很显然,我们不能直接获得 一个完整的数据结构,所以需要自己在内部进行处理。同时,因为在Tree上有一些公有的属性,但是TreeNode没办法获得这些属性,在开源项目中,他是通过使用react的context来处理的,在我的实现中我采取了父组件一路通过props传递属性实现。
  • 在判断子结点的状态时,我们可以直接为其传入一个bool值来决定他的状态。但是我们不可能在treeNode上手动计算这个bool值,所以我们需要做一层代理,根据某种逻辑计算出这个结点的状态,然后使用React.cloneElement在treeNode上加上他的状态。
  • 对于子结点状态的判断,我们之前说过,应该由父节点统一决定。所以我们在父节点上维护几个数组,分别保存 全选/半选/展开 状态下各个结点的key值。同时,我们在初始化时,需要遍历一遍整个结构,生成一个打平的数组来保存整个树。当点击某个结点后,使用该数据结构和旧的状态数组生成新的状态数组,再有父节点统一下发各结点状态。
  • 对于如何判断结点状态,我们采取下列逻辑:对于某个结点,我们设置checked和halfchecked,他们的初始值分别为true和false。随后遍历其子结点,如果子结点为全选状态,设置其halfchecked为true,否则设置其checked为false。这样遍历完字节点后我们就能得到当前结点的状态checked和halfchecked。checked的优先级高于halfchecked。如果两个都为false证明这个结点是未选中结点。

三、具体实现

  有了基本思路以后,我们来具体实现:
  首先是对其进行遍历来生成一个初始的数据结构,方便我们后续使用。getDerivedStateFromProps是react16中的一个新的生命周期函数。

//tree.js
 static getDerivedStateFromProps(props, state) {
   
   const treeNodes = props.children;
   const entities = {
   };
   for(let i = 0, len = treeNodes.length; i < len; i++) 
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值