虚拟DOM
一、虚拟 DOM
1、虚拟 DOM 是什么?
一个能代表 DOM 树的对象,通常含有标签名、标签上的属性,事件监听以及其他属性
2、虚拟 DOM 的优点
- 减少 DOM 操作
- 虚拟 DOM 可以将多次 DOM 操作合并成一次操作。比如添加 1000 个节点,DOM 是一个一个操作,虚拟 DOM 可以减少 DOM 操作次数
- 虚拟 DOM 借助 DOM diff 可以省掉多余操作。比如添加 1000 个节点,只有 10 个是新增的。虚拟 DOM 可以减少操作范围
- 跨平台
- 虚拟 DOM 是一个对象,不仅可以变成 DOM 还可以变成小程序,ios 应用,本质上是一个 JS 对象
3、虚拟 DOM 的缺点
需要额外的创建函数,比如createElement,或h,可以通过 JSX 和 XML 简化,但严重依赖打包工具
二、DOM diff
DOM diff 是虚拟 DOM 的对比算法
1、DOM diff 的优点
diff 算法会帮助我们计算出虚拟 DOM 中真正变化的部分,并只针对该部分进行实际 DOM 操作,而非重新渲染整个页面,从而保证了每次操作更新后页面的高效渲染。
大概逻辑
Tree diff
- 将新旧两棵树逐层对比,找出哪些节点需要更新
- 如果节点是组件就看 Component diff
- 如果节点是标签就看 Element diff
Component diff
- 如果节点是组件,就先看组件类型
- 类型不同直接替换(删除旧的)
- 类型相同则只更新属性
- 然后深入组件做 Tree diff(递归)
Element diff
- 如果节点是原生标签,则看标签名
- 标签名不同直接替换,相同则只更新属性
- 然后进入标签后代做 Tree diff(递归)
2、DOM diff 的问题
- DOM diff 在同级对比时会出现 bug。由于计算机总是从上到下,从做左到右计算的,在同级别有多个节点,删除前面的节点时,会被 diff 算法认为是修改了前面的节点,删除了后面的节点,这就会导致渲染不符合预期。
- 解决方法是,在每一个节点增加一个唯一的 key 属性,用来标识节点。这也是 Vue 和 React 在使用循环时需要添加 key 属性的原因