浅谈 虚拟Dom (VitrualDom)

本文将简单为大家讲解虚拟Dom与diff算法

众所周知,真实的dom就是浏览器渲染而成的一棵真实的dom树。然而,当我们每一次对这一棵真实的dom树进行修改的时候,我们的浏览器并不会去寻找你到底对这棵真实的dom树哪里进行修改了,浏览器只会直接砍掉这棵真实的dom树,再把你修改好的dom重新渲染一棵。 为了避免每一次修改同一个dom树,浏览器每一次都”砍树“的暴力拆迁,尽量减少Dom操作的性能开销。由此,虚拟dom应运而生。我们使用的Vue、React等框架就采用了虚拟dom。

  • 什么是虚拟dom

    虚拟dom其实是里面内存型对象(js内存对象)属于内存数据,是真实dom的一层映射。一般用在循环里面,防止出错,并且加快效率。简单来说,虚拟dom就是通过一些特别的步骤来避免整棵 DOM 树变更。步骤具体如下:

    1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中

    2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(使用diff算法),记录两棵树差异

    3. 把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了

      

  • 实现虚拟dom

  1. 内存中生成一颗虚拟dom树
    //我们将要进行的数据变化放在arr里面
    var data = {
        arr:[]
    }
    //内存中生成一颗虚拟dom树
    var vDom = {
        tag:"div",//<div></div>
        attr:{
            id:"content"//<div id="content"></div>
        },
        children:[
            {tag:"p",content:1},//<p>1</p>
            {tag:"ul",attrs:{className:"list-group"}},//<ul class="list-group"></ul>
            {tag:"div",content:2},//<div>2</div>
        ]
    }
  2. 将内存中的虚拟dom树初始化渲染成真实dom树
    <div id="content">
        <p>1</p>
        <ul class="list-group"></ul>
        <div>2</div>
    </div>
  3. 当我们修改data里面的数据的时候
    data.arr.push("<li>listOne</li>")
    data.arr.push("<li>listTwo</li>")
    data.arr.push("<li>listThree</li>")
  4. 将之前的虚拟dom树结合新的数据生成一颗新的虚拟dom树
    var newDom = {
        tag:"div",//<div></div>
        attr:{
            id:"content"//<div id="content"></div>
        },
        children:[
            {tag:"p",content:1},//<p>1</p>
            {tag:"ul",attrs:{className:"list-group"},children:[//<ul class="list-group"></ul>
                {tag:"li",content:"listOne"},//<li>listOne</li>
                {tag:"li",content:"listTwo"},//<li>listTwo</li>
                {tag:"li",content:"listThree"}//<li>listThree</li>
            ]},
            {tag:"div",content:2},//<div>2</div>
        ]
    }
  5. 将此次生成好的新的虚拟dom树与上一次的虚拟dom树结构进行对比,对比差异(diff算法)
    • 虚拟dom采用diff算法同一个层级的元素进行对比


    • 深度优先遍历,记录差异:
      对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记,每遍历到一个节点就把该节点和新的的树进行对比。
  6. 将对比出来的差异的部分进行重新真实dom结构的渲染,视图就更新了
    <div id="content">
        <p>1</p>
        <ul class="list-group">
            <li>listOne</li>
            <li>listTwo</li>
            <li>listThree</li>
        </ul>
        <div>2</div>
    </div>
posted @ 2020-03-23 20:41  Welin  阅读(309)  评论(0)    收藏  举报