简介
(2022-05 补充:作为十年前的插件,zTree 应该算是尽力了,但对于现在来说,这套技术太落后了,现在要考虑的就是虚拟列表的方式,但是 zTree 的架构没办法做到这一点,除非我啥时候完全重新做一套)
有不少朋友的项目中都会牵扯到大数据量的加载,如果处理不好,会直接导致页面停滞卡顿,用户操作不便。zTree 目前也并没有完善的解决方案,本篇文章将对这个问题详细描述。 看这篇文档时,你需要对照 API 文档进行学习(http://www.treejs.cn/v3/api.php)
zTree 渲染 DOM 的优化方案
在 “1.08 DOM 结构 & 延迟加载” 中已经讲过,zTree 初始化节点时对于不需要显示的节点不立刻生成 DOM,从而达到性能优化的目的。
通过这个 Demo 可以看到一次性加载大数据时的优化效果。但是这里面有非常重要的几点需要强调(在 Demo 的右侧也都有描述):
- 对于每级节点最多一百左右,但总节点数几千甚至几万,且不是全部展开的数据,一次性加载的效果最明显,速度非常快。
因为每一次操作需要渲染的 DOM 数量很少
- 对于某一级节点数就多达几千的情况 延迟加载无效,这种情况建议考虑分页异步加载。
因为这样直接导致 zTree 的优化方案失效了,大量 DOM 的创建会直接导致页面卡顿
- 对于全部节点都展开显示的情况,延迟加载无效,这种情况建议不要全部展开。
因为这样就让 zTree 的延迟加载方案完全无意义,试想一下,成千上万的节点同时显示,用户看的过来么?所以当你遇到这种需求时,先去问一问这个需求合理么?
- 显示 checkbox / radio 会造成一定程度的性能下降。
因为会增加一些 DOM 操作,所以会适当影响性能
- 利用 addDiyDom 功能增加自定义控件会影响速度,影响程度受节点数量而定。
因为增加了 DOM 的操作
- 利用 onNodeCreated 事件回调函数对节点 DOM 进行操作会影响速度,影响程度受节点数量而定。
因为增加了 DOM 的操作
对于大数据量节点加载的方案分析
下面针对一些案例,讲解一下具体的解决方案
1、采用异步加载方案
这个 Demo 并不特殊,他只是一个简单的异步加载的演示,为什么还要强调这个呢?这是因为异步加载这个操作本身就是为了提升效率的。zTree 的延迟加载处理其实是被动的,而异步加载对于页面 DOM 来说就是用户想看什么就生成什么,不想看的就没必要去加载。成千上万的节点数据,用户操作时可能只看其中很少的一部分,每次异步加载时只加载当前这一级的节点,没有了大量 DOM 的渲染,自然也就提升了性能。
缺点:
- 如果你的数据结构分布并不均匀,某一个父节点下一级的子节点就有成千上万个,那么就不适合这么使用,因为他无法避免大量 DOM 的渲染 怎么办?请看下面两种方案
2、分批次异步加载方案
查看这个 Demo 的源码,你会发现,针对同一级节点数量庞大时,利用 reAsyncChildNodes 和 setTimeout 实现了程序自动追加子节点的效果。 实现此方案需要注意以下几点:
- 在 onAsyncSuccess 回调中去控制判断子节点是否加载完毕,是否需要开启新的 ajax 去加载剩余节点(也就是加载完一部分再去加载下一部分)
- reAsyncChildNodes 方法要使用 追加方式,不要使用 刷新方式
- 利用 url 或 otherParams 参数变换传递的页码
- 你的服务端接口一定要能够分页输出节点数据
缺点:
- 此方法并不能解决加载慢的问题,相反只会让最终结果出现的更慢,只是可以有限度的避免浏览器假死,而且显示的节点越多就越慢。 所以,这个方案最大的问题是,虽然他让加载大量 DOM 的过程延缓了,但仍然无法避免最终页面上会有几万或更多的节点 DOM 被渲染,从而导致页面卡顿,如果你的节点数量太多太多,以至于这个方案都无法满足,那么再看下面这个方案吧。
3、分页加载方案
从最基本的操作来说,这个方案依然是利用了 reAsyncChildNodes 方法,只不过他利用的是刷新,而不是追加! 实现此方案需要注意以下几点:
- 每次加载子节点时,只根据当前页码加载本页的子节点集合
- reAsyncChildNodes 方法要使用 刷新方式,不要使用 追加方式
- 利用 url 或 otherParams 参数变换传递的页码
- 你的服务端接口一定要能够分页输出节点数据
缺点:
- 如果很多父节点的子节点都有极大的数据量,那么你的树上针对于这些父节点都要去显示 翻页按钮,做起来好麻烦,而且页面展示效果并不好看
- 对于 checkbox 的关联关系无能为力,只能每次翻页后进行修正。Demo 中并没有实现这种处理
- 从 zTree 得到的节点数据只有当前页的节点数据,你可以在每次翻页后自行保存每页的数据,作为缓存,具体情况要根据实际需求来决定
总结
总之,zTree 的方案并不完美,但如果以上这些方式都不适合你,那么你也必须要去思考是不是应该变换一下你的需求方案了,至少你要有一个原则:“避免页面上同时渲染大量 DOM”,虽然现在的电脑性能都很好了,浏览器也越来越强大了,但实际上还是有限度的,并不能无限的肆意滥用。
最后,我要再次强调:千万不要使用了异步加载方案,同时拥有大数据量的时候,还要任性的要求初始化后展开全部节点!!!! 请你问一下自己,这么做的时候,到底为了什么??