最近公司内部正好要准备技术分享,所以花了大概三个月的时间去学习关于domdiff算法的知识,文章会结合源码和图片尽量的深入浅出,把整个过程说的明白、讲的清晰。

文章分三篇:

  • 认识virtual dom && diff算法演进史
  • react的dom diff策略
  • vue的dom diff策略

什么是virtual dom?

简单一句话,就是用javascript模拟出来的dom对象

为什么要有virtual dom?

1、实际应用中会频繁操作dom节点
2、操作dom节点的成本很高(jquery时代),每次操作会导致页面的重绘和重排
3、而单纯操作js的成本很低(v8引擎),如果能利用js从而有效减少重绘重排的次数,那么我们页面性能会大幅度提升

dom diff算法是什么?

因为有了vdom,那怎么样才能减少节点操作的次数,diff算法就应运而生了。它的核心功能就是对比操作前后两个dom树和节点的异同,将差异记录到差异patch队列中最后将更新一步到位。整个diif流程分为三步,如下图,patch就是将记录的差异队列同步到真实dom的过程。

深度解析dom diff算法(一)

dom diff算法演进史

有伙伴想做深入研究的话可以去看看每种算法的源码,我们核心讲解vue和react的diff实现,相关链接在文章末尾,这里要强调一点的是我们目前主流前端框架的diff算法都是在snabbdom.js基础上优化来的。

深度解析dom diff算法(一)

传统diff算法

传统diff算法就是将新旧两棵树的节点依次进行对比,然后进行dom树的更新

深度解析dom diff算法(一)

上图所示,传统diff算法时间复杂度为O(n的三次方),原因如下,假定新旧树的节点数目都为n:
1、新dom树中某一个节点和旧树所有节点依次遍历比较,复杂度为O(n)
2、新dom总共n个节点,每个节点遍历n次,复杂度为O(n)
3、遍历完成发现旧dom中的某个节点被删除/添加/更新,这里需要进行最小距离转换(transform cost), 时间复杂度均为O(n)。
这里严格来讲复杂度其实是O(m*(1+logmn)),但是我们假定这里的前提是m=n
4、综上,复杂度变为O(n
n*n)

前两个n的复杂度很好理解,最后的最小转换方式的复杂度怎么算出来的呢?这里涉及到了一个叫做最小编辑距离算法,如果深入讲解的话又是万字长文。一篇有参考性的文章,有兴趣的伙伴可以去研究:https://www.zhihu.com/question/66851503

参考文章链接:

https://github.com/joelrich/citojs 【cito.js】
https://github.com/snabbdom/snabbdom/blob/v0.7.3/src/snabbdom.ts#L179【snabbdom.js】

相关文章: