基于MPTT的虚拟树【前言】

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

1. 什么是虚拟树

在通常的树结构中,它是一个二维结构,即:它除了有高度,还有深度,它在前端页面中的表现如下:

image.png

对于传统结构的树来说,在大数据量下想要有比较优秀表现,我想到的唯一方式就是使用异步加载,但是异步加载还会有一个问题:当随着节点展开数量越多,性能下降越快。
如果要解决节点展开数量导致性能下降的问题,就只能选择其他途径-虚拟列表技术是很成熟的一个方案。
虚拟列表技术的原理就是只显示可选择区域中的数据。比如:显示区域的高度是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, },
]

从上面可以看出:

  1. 如果要查询所有子节点,只要判断 节点lLeaf大于当前lLeaf节点,以及节点rLeaf小于当前rLeaf节点即可
  2. 如果要查询所有父节点,只要把第1点的反过来做即可。


    unp0k-3beli.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容