美文网首页
虚拟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