美文网首页
虚拟DOM观察

虚拟DOM观察

作者: fourkilometers | 来源:发表于2018-12-31 21:45 被阅读0次

自从react流行起来后,前端开发者们对虚拟DOM的研究就从未停止过,现在开源世界里已经有了非常多优秀的虚拟DOM库供大家使用。虚拟DOM这项技术能流行起来大概有三个原因。

  • 通过减少真实DOM操作提高系统运行效率
  • 降低维护状态 -> 视图的复杂程度
  • 帮助开发者轻松实现前端组件化

一、虚拟DOM的工作过程

虚拟DOM以virtual node为基础单元构造虚拟DOM树,然后随系统状态的变化来操作真实DOM。大致的工作过程如下:

  1. 创建virtual node,构建起虚拟DOM树
  2. 根据虚拟DOM树创建真实DOM树
  3. 系统状态变化,产生新的虚拟DOM树
  4. 拿新树与旧树做diff操作,分析出两棵树的差异
  5. 针对差异对真实DOM做修改

二、虚拟DOM节点

虚拟DOM节点(virtual node)对应真实DOM中的HTML Element,它的构造非常简单,只需要提供标签名,属性,子节点和一个用于区分兄弟节点的key。它的结构和真实DOM里的元素非常类似。

function VirtualNode(tagName, properties, children, key) {
    this.tagName = tagName
    this.properties = properties || null
    this.children = children || []
    this.key = key != null ? String(key) : undefined
    ...
}

一层一层的virtual node组成了一棵虚拟DOM树

三、diff

每棵树都有一个根节点,从根节点做遍历是分析树最快的方式。遍历的方式可以选择深度优先遍历或者广度优先遍历。为了降低diff的复杂度,一般的虚拟DOM库都会设置两个前提:

  • 类型不同(tagName不同)的两个virtual node被认为是完全不一样的,即使它们的所有属性、子节点和key都一样
  • 对于同一层级的一组子节点,它们可以通过唯一的 key值进行区分
    接下来是具体的diff过程
1.不同类型节点的对比

对于不同类型的两个节点,反映到真实DOM上的操作是,直接删除旧的节点,然后插入新的节点

2.相同类型节点的对比

根据key值分两种情况, key值相同的两个节点会接着比较属性和子节点,key值不同的情况下,和不同类型节点一样,删除旧的节点,插入新的节点。

3.virtual node节点列表对比

这里需要强调的是,节点列表里的每一项都没有key值的情况下,旧列表中的所有项都不会被重新利用,反映到真实DOM节点就是直接用新的元素列表代替旧的元素列表,这样情况没有任何可以优化的地方。所以这里说的是每一项带有唯一key值的virutal node节点列表之间的对比。
节点列表之间的对比类似于比较两个字符串

  A:  [a b c d e f g] 
  B:  [a c b h f e g] 

首先分析出可重用的节点,如abcefg,通过对比两个列表的key值得出一个新的临时列表C,在B列表中没有的用-1表示,把B列表中存在但A列表不存在的放到最后。

  C:  [a b c -1 e f g h] 

然后做一下处理,记录下值是-1的节点的索引,这些节点对应的DOM元素会被删除,在C列表中也删除-1的值

  C:  [a b c e f g h] 

接下来同时遍历B、C两个列表,对比相同位置下的节点,根据下面的规则来制定出移动真实DOM元素次数最少的步骤。

  • 值相同,对应的真实DOM不移动,如a节点
  • 值不同,记录下当前索引,把C列表中的节点也记录下来,它对应的DOM元素会被插入到刚才记录下的索引处,如c会被插入到列表第二的位置
    最后,得到两个列表对比的分析结果

四、把差异应用到真正的DOM树上

和diff过程采用的遍历方式一样,遍历一次整个真实DOM树,最后根据记录的差异来操作DOM元素。

五、小结

本文大致讲解了虚拟DOM的工作过程和Diff原理,参考的是virtual-dom这个虚拟DOM库,同时我自己用这个库实现了一个todo-list应用 todolist-virtualdom
,帮助大家理解虚拟DOM的使用方法和工作过程。

参考资料

深度剖析:如何实现一个 Virtual DOM 算法
深入浅出 React(四):虚拟 DOM Diff 算法解析
Reconciliation

相关文章

网友评论

      本文标题:虚拟DOM观察

      本文链接:https://www.haomeiwen.com/subject/oezplqtx.html