前段时间,接触到一个项目,需要将两万多条树型数据加载在前端供用户使用(有各种原因导致异步方式不能被使用)。因为前端使用的是vue,所以就想找一个以vue为基础的高性能的树插件,找了一圈才发现基于vue的树插件要不就是使用原始的方式,要不就是虽然使用了虚拟树技术但是却是另一个大组件中的小组件,而且样式修改方面也不是那么方便。最终为了方便起见,还是选择ztree然后在外面套了一层壳使其操作起来像vue方式,但这种方式还是有不少问题,其中一个就是要包含一个巨大的jquery。因为这个原因,所以后面就自己搞了个虚拟树的组件给以后的项目使用。
1. 什么是虚拟树
在通常的树结构中,它是一个二维结构,即:它除了有高度,还有深度,它在前端页面中的表现如下:

对于传统结构的树来说,在大数据量下想要有比较优秀表现,我想到的唯一方式就是使用异步加载,但是异步加载还会有一个问题:当随着节点展开数量越多,性能下降越快。
如果要解决节点展开数量导致性能下降的问题,就只能选择其他途径-虚拟列表技术是很成熟的一个方案。
虚拟列表技术的原理就是只显示可选择区域中的数据。比如:显示区域的高度是400px,在400px的显示区域中只能显示16条数据,那么我就只在数组中读取16条数据显示在页面中。其显示流程如下:
- 拖动滚动条的时候,计算出区域坐标
- 通过坐标,从数组中获取相应数据
- 清空页面数据,加载新的数据
虚拟树技术即是以虚拟列表技术为基础进行的扩展,但其需要解决以下问题:
- 层次问题:虚拟树因为是树结构,所以在展现方面应该有层次,这个层次可通过保存深度方式解决。页面展现时,根据深度将其移动到合适的位置
- 树的展开与闭合:虚拟树的枝节点因为可以操作展开与闭合,所以需要处理下级节点的展现问题
-
树的多选问题【checkbox】:对于叶节点来说,checkbox有两种状态:选中,未选中。而对于枝节点【即有下级节点】来说,checkbox有三种状态:选中,未选中以及半选状态,而且,对于枝节点来说,每次节点的选择,都需要判断枝节点是处于哪种状态。
下面是虚拟树:
image.png
2. 如何创建一个支持虚拟树的数组
从上面的说明可以看到,虚拟树其实就是一个比较特殊的,可以支持判断是否为某一结点的下级数据的列表结构,且应该是一个按照树结构排好序的列表结构。要按这个结构创建一个列表大体上有以下两种方式:
1. key方式
key方式主要是在key的取值方面做手脚,通过解析key就可以知道当前节点处于哪里,节点下所有子节点有哪些。
key如下:
0
0-0
0-0-0
0-0-0-0
0-0-0-1
0-0-0-2
0-0-1
从上面可以看到,这种方式通过key的结构来判断下级结点与上级父节点。
2. 预排序树(MPTT)方式
预排序树使用左右节点值的方式来处理:排序、父子节点判断,使用深度来处理节点的层级。
预排序树结构如下:
[
{ lLeaf: 0, rLeaf: 9, deep: 1, },
{ lLeaf: 1, rLeaf: 8, deep: 2, },
{ lLeaf: 2, rLeaf: 3, deep: 3, },
{ lLeaf: 4, rLeaf: 5, deep: 3, },
{ lLeaf: 6, rLeaf: 7, deep: 3, },
]
从上面可以看出:
- 如果要查询所有子节点,只要判断 节点lLeaf大于当前lLeaf节点,以及节点rLeaf小于当前rLeaf节点即可
-
如果要查询所有父节点,只要把第1点的反过来做即可。
unp0k-3beli.gif

