虚拟 DOM 是什么
虚拟 DOM(Virtual DOM)是一种轻量级的 JavaScript 对象,它是真实 DOM 的抽象表示。在 Vue 等前端框架中,虚拟 DOM 作为真实 DOM 的抽象层,以对象树的形式存储在内存中,包含了真实 DOM 的相关信息,如标签名、属性、子节点等。
真实 DOM 是浏览器用于呈现网页的树形结构,操作真实 DOM 的代价比较高,因为每次修改都会引发浏览器的重排(reflow)和重绘(repaint),这会消耗大量的性能。而虚拟 DOM 的出现就是为了优化这个过程,通过在内存中对虚拟 DOM 进行操作和比较,找出最小的更新量,然后一次性将这些更新应用到真实 DOM 上,从而减少对真实 DOM 的直接操作,提高渲染效率。
虚拟 DOM 是如何工作的
1. 初始化阶段
- 模板编译:Vue 会将用户编写的模板字符串(如
<div>{ { message }}</div>
)编译成渲染函数(render
函数)。这个过程包括解析模板为抽象语法树(AST),对 AST 进行优化,最后根据优化后的 AST 生成渲染函数。// 示例渲染函数 function render() { return createVNode('div', null, this.message); }
- 生成虚拟 DOM:当 Vue 实例首次渲染时,会调用渲染函数,渲染函数会返回一个虚拟 DOM 节点(VNode)。这个虚拟 DOM 节点是一个普通的 JavaScript 对象,它描述了真实 DOM 的结构和属性。
// 简单的虚拟 DOM 节点示例 const vnode = { tag: 'div', data: { class: 'container' }, children: [ { tag: 'span', text: 'Hello, Vue!' } ] };
- 挂载到真实 DOM:Vue 会根据生成的虚拟 DOM 创建对应的真实 DOM 节点,并将其挂载到页面中指定的位置(即
el
选项指定的元素)。
2. 更新阶段
- 数据变化触发重新渲染:当 Vue 实例中的响应式数据发生变化时,会触发重新渲染。Vue 会再次调用渲染函数,生成新的虚拟 DOM。
// 假设 data 中有一个 message 属性 this.message = 'New message'; // 触发重新渲染,生成新的虚拟 DOM
- Diff 算法比较差异:为了找出新旧虚拟 DOM 之间的差异,Vue 使用了 Diff 算法。Diff 算法会对新旧虚拟 DOM 进行比较,找出需要更新的部分。Diff 算法采用了双指针和 key 的策略来提高比较效率。
- 同层比较:Diff 算法只对同层的节点进行比较,不会跨层级比较,这样可以减少比较的复杂度。
- key 的作用:当节点有唯一的
key
时,Diff 算法可以更准确地识别节点的变化,例如节点的移动、删除和新增。
- 更新真实 DOM:根据 Diff 算法的比较结果,Vue 会将需要更新的部分应用到真实 DOM 上。这个过程只更新发生变化的部分,而不是重新渲染整个 DOM 树,从而提高了性能。
总结
虚拟 DOM 通过在内存中进行操作和比较,减少了对真实 DOM 的直接操作,从而提高了渲染效率。它在初始化阶段生成虚拟 DOM 并挂载到真实 DOM,在更新阶段通过 Diff 算法找出差异并更新真实 DOM。