(Vue3)对虚拟DOM的相关概念进行总结

30 阅读3分钟

一、DOM树

1、定义:

用于表示基于HTML或者XML的标记语言文档并能与之交互的API。它是加载在浏览器中的文档模型,可以将文档表示为节点树,或称 DOM 树,其中每个节点代表文档的一部分。

2、作用:

允许在浏览器中运行的代码访问文档中的每个节点并与之交互。可以创建、移动和更改节点,还可以将事件监听器添加到节点,并在特定事件发生时触发。

3、性能瓶颈

直接操作DOM可能引发浏览器的重排和重绘。如果频繁或者复杂地操作DOM,会大量消耗性能,导致页面卡顿。

二、虚拟DOM

1、实质

一个描述真实DOM结构的js对象

const vnode = {
  type: 'div',
  props: {
    id: 'hello'
  },
  children: [
    /* 更多 vnode */
  ]
}

2、作用

提供一种高效的方式来计算出dom的最小变更,并批量、高效地应用到真实DOM上。

优点:

  • “声明式UI”技术基础。开发者直接告诉程序“在状态A下,视图应该是B”,而不是用命令式代码一步步指挥(“如果A变了,就找到C元素,然后修改它的D属性”)。大大简化了UI开发的复杂度。
  • 抽象与跨平台:虚拟DOM最大的价值之一是提供了抽象层。开发者通过描述“应该是什么样子”来编程,而不必亲自操作具体的DOM API。这使得Vue等框架不仅可以渲染到浏览器DOM,还能相对容易地渲染到原生移动应用(如Weex/NativeScript)、Canvas、甚至是终端命令行界面。渲染器(Renderer)接收虚拟DOM并转换为特定平台的UI。

3、过程

  • 编译:Vue模版被编译为渲染函数(用来返回虚拟DOM树)的函数,
  • 挂载(mount):初次渲染时,根据虚拟DOM树创建整个真实DOM树
  • 更新(patch/diffing):当状态发生变化,会生成新的虚拟DOM树。渲染器通过Diff算法将新旧两棵虚拟DOM树进行比对,精确找出差异所在。(优点:算法会高效地遍历两棵树,只在同一层级进行比较,避免了跨层级的开销,只针对发生变化的部分生成对应的DOM操作指令)
  • 批量提交:将计算出的所有DOM操作批量作用到真实DOM上,减少了直接操作DOM的次数,避免不必要的重排重绘。

4、不足

  • 需要额外的内存来创建和存储虚拟DOM,需要CPU时间来进行Diff计算。是用JS的计算开销来换取减少DOM操作开销的方法。(对大部分应用来说是值得的,因为JS计算比DOM操作更快)
  • 并非是绝对最快的:手工编写优化的命令式DOM操作可能比虚拟DOM的更新更快

三、Vue3 生命周期

组合式 API 中的 setup() 钩子会在所有选项式 API 钩子之前调用

image.png

nextTick()

在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。

nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。

优点:等待Vue完成所有组件的DOM更新,保证操作的是最终的DOM。