标签: diff算法

  • Vue虚拟DOM与diff算法

    就地复用

    Vue会尽可能的就地(同层级,同位置),对比虚拟dom,复用旧dom结构,进行差异化更新。

    虚拟DOM

    真实DOM

    • HTML渲染出来的DOM树
    • 每个标签都是树的节点
    • 每个节点拥有非常多的属性 由于真实DOM的属性过多,导致对比差异会消耗过多的性能,且有很多无需遍历对比的属性,这样效率很低。

    虚拟DOM

    本质是JS对象,保存渲染真实DOM时的必要属性。

    <template>
    <div id="app">
      <h1 class="title">标题</h1>
    </div>
    </template>
    
    <script>
     const virtualDOM = {
       type:'div',
       attributes:[{id:'app'}],
       children:[{
         type:'h1',
         attributes:[{class:"title"}],
         text:'标题'
       }]
     }
    </script>
    渲染过程
    1. template渲染成虚拟DOM
    2. 根据虚拟DOM渲染成真实的DOM
    数据发生更新
    1. 重新生成一份新的虚拟DOM
    2. 对比新的虚拟DOM和旧的虚拟DOM,找到不同的地方
    3. 最后统一更新真实的DOM
    虚拟DOM的作用

    可以在内存中创建虚拟DOM,快速比较变化的部分, 然后给真实DOM打补丁(更新)

    虚拟DOM总结

    虚拟DOM相比真实DOM只保留了渲染时必要的属性,可以更高效地对比DOM新旧差异,进行差异化更新。

    diff算法

    虚拟DOM内部的比对过程称为diff算法

    策略一

    先同层级根元素比较,如果根元素变化,那么不考虑复用,整个dom树删除重建

    策略二

    对比同级兄弟元素时,默认按照下标进行对比复用。如果数组顺序没有发生改变,性能是高效的。

    如果数组的顺序发生了变化,性能并不高

    策略三

    同级兄弟元素,在设置了key后,会让相同key的元素进行对比。

    key必须是字符串或者数字,且必须唯一

    (尽量不用遍历的索引作为key,参考策略二中数组的顺序发生变化)

    总结

    • 设置了key在DOM更新时会按照相同的key进行新旧元素比较(不设置则默认为索引)
    • 目的:提高更新时的性能
    • key必须是字符串或者数字,且必须唯一