虚拟DOM和DOM diff

136 阅读3分钟
一 虚拟DOM是什么
  1. 虚拟DOM是相对于真实DOM而言的,一个能代表DOM树的js对象,通常含有标签名,标签上的属性,事件监听和子元素们,以及其他属性。
二 虚拟DOM的优点
  1. 能减少DOM操作
    (1) 能减少DOM操作的次数
    比如向页面中添加1000个div,js会一个一个的添加,操作1000次,而虚拟DOM可以将多次操作合并为一次操作。
    (2) 能减少DOM操作的范围
    虚拟DOM借助DOM diff可以把多余的操作省掉,比如页面中添加1000个节点,其中只有10个是新增的。通过对比区分新旧节点,如果发现有些节点已经在页面了,不需要更新,他就不更新了,减少DOM操作的范围。
  2. 能跨平台渲染
    因为虚拟DOM本质上是一个js对象,他可以变成DOM树,也可以变成ios上的树,安卓上的树。
三 虚拟DOM的缺点
  1. 需要用额外的创建函数来创建DOM,如createElement或h。
  2. 可以简化,React使用JSX语法,Vue使用模板语法。但是这种简化写法严重依赖于打包工具,需要额外的构建过程。如果不打包的话,js是不认识的。
    <div className="red" onClick={fn}>
       <span>span1</span>
       <span>span2</span>
    </div>
    //通过babel转为createElement形式

    <div class="red" @click="fn">
       <span>span1</span>
       <span>span2</span>
    </div>
    //通过vue-loader转为h形式
四 DOM操作慢?虚拟DOM快?
  1. DOM操作慢是相对于JS原生API来讲的,比如数组操作。因为DOM操作需要跨线程通信,所以相对慢。
  2. 任何基于DOM的库(vue/react)都不可能在操作DOM时比DOM快
  3. 只能说在某些情况下,虚拟DOM快,比如上面所讲虚拟DOM的优点
五 DOM diff

给定任意两棵树,采用先序深度优先遍历的算法找到最少的转换步骤。简单来讲就是对比新旧虚拟DOM这两个对象差异,创建出补丁,描述改变的内容,将这个补丁用来更新DOM。主要过程包括

  1. tree diff
    (1) 将新旧两棵树逐层对比,找出哪些节点需要更新
    (2) 如果节点是组件就看 Component diff
    (3) 如果节点是标签就看 Element diff
  2. component diff
    (1) 如果节点是组件,就先看组件类型
    (2) 类型不同直接替换(删除旧的)
    (3) 类型相同则只更新属性
    (4) 然后深入组件做 Tree diff(递归)
  3. element diff
    (1) 如果节点是原生标签,则看标签名
    (2) 标签名不同直接替换,相同则只更新属性
    (3) 然后进入标签后代做 Tree diff(递归)
六 DOM diff的优点

通过对比新旧虚拟DOM这两个对象的差异(Diff算法),最终只把变化的部分重新渲染,提高渲染效率的过程。

七 DOM diff的缺点

同级节点对比存在 bug,比如Vue中,v-for使用时必须添加唯一的可以标识节点的key。