# 简介
虚拟DOM(Virtual DOM)是近年来在前端开发中崭露头角的概念,它在提升性能、优化渲染和改善用户体验方面发挥了重要的作用。本章将深入探索虚拟DOM的工作原理和背后的思想。我们将介绍虚拟DOM是如何在Vue中发挥作用的。
# 什么是虚拟DOM
虚拟DOM是一个JavaScript对象
的表示,它是对真实DOM
的轻量级抽象。如下示例:
<div class="button" id="btn">这是一个按钮</div> { tag:'div', // 元素标签 attrs:{ // 属性 class:'button', id:'btn' }, text:'这是一个按钮', // 文本内容 children:[] // 子元素 }
成功
2
3
4
5
6
7
8
9
10
11
像这样,可以用一个JavaScript对象
描述真实DOM
节点的,我们称这个JavaScript对象
是真实DOM
节点的虚拟DOM
节点
# 为什么要用虚拟DOM
我们知道,想要在视图中渲染,势必就要操作真实DOM
,而操作真实DOM
又是非常耗费性能的。因为在浏览器标准中,真实DOM
就是一个非常复杂的结构。我们可以尝试用以下方式打印真实DOM
来查看
可以看到创建一个空div的真实DOM
都十分的庞大,更何况我们在复杂的应用中需要操作大量的真实DOM
,还有较为复杂的结构,这势必会对性能造成一定的影响。
所以如何尽量真实DOM
的操作,成了框架设计中一个避不开的环节。在这个基础上,虚拟DOM
应运而生。
# 虚拟DOM如何节省性能
虚拟DOM通过在内存中构建一个轻量级的DOM树来解决这个问题。当应用程序的状态发生变化时,我们首先在虚拟DOM上进行修改,而不是直接操作真实DOM。通过比较新旧虚拟DOM的差异,我们可以确定哪些部分需要更新,并仅对这些部分进行实际的DOM操作。这种优化技术被称为"DOM Diffing"。
虚拟DOM的工作流程如下:
- 初始渲染:首次渲染时,将真实DOM转换为虚拟DOM。
- 状态变更:当应用程序的状态发生变化时,修改虚拟DOM树。
- 虚拟DOM Diffing:比较新旧虚拟DOM树的差异,找出需要更新的部分。
- 生成变更集:根据差异生成最小化的DOM操作序列。
- 应用变更:将变更应用于真实DOM,更新页面展示。
通过使用虚拟DOM,我们可以减少真实DOM操作的次数,并最大程度地减少重绘和回流的成本。这种优化能够显著提升性能,特别是在大型复杂的应用程序中,或是需要频繁更新的动态内容中。
# 虚拟DOM比真实DOM性能消耗更小么?
先说答案,是也不是。
这是什么意思呢?
我们先假设一个场景,我需要用原生JavaScript
更改div的内容,代码如下:
const div = document.getElementById('div'); div.textContent = 'changed';
成功
2
现在思考下,还有没有比这个性能更好的替代方案?
很显然,并没有。可以看到,我们使用这种命令式代码
可以做到极致的性能优化,因为我们知道哪里发生变化了,我们直接用命令去更新即可。
如果这个场景换成Vue这种声明式代码
呢?会经历如下过程
- 首次渲染时,将真实DOM转换为虚拟DOM。
- 代表内容的变量字段发生变化,修改新的虚拟DOM树。
- 对比新旧虚拟DOM,找到差异。
- 根据差异更新给真实DOM树
可以看到,在有虚拟DOM
后,需要先去找到差异,再去更新真实DOM
。这会比我们直接写真实DOM
多一些性能消耗,所以这时候虚拟DOM
并没有比真实DOM
性能消耗更小。
有人会问了,那为什么还要使用虚拟DOM
?
原因有两条:
- 在实际开发中,我们很难写出绝对优化的
命令式代码
- 类似原生js或JQuery的
命令式代码
在开发中,我们需要手动完成真实DOM
的创建、编辑、删除等工作,提升了开发过程中的心智负担。
回到问题本身,虚拟DOM
比真实DOM
性能消耗更小么?
完整的答案应该是,在绝对优化代码的情况下,虚拟DOM
比真实DOM
性能消耗更大,因为要多一个找到差异的性能消耗。但在实际开发过程中,虚拟DOM
比真实DOM
性能消耗更小,因为我们写的代码无法做到绝对优化。
# 总结
虚拟DOM是一个JavaScript对象的表示,它是对真实DOM的轻量级抽象。在传统的前端开发中,我们直接操作真实的DOM来进行页面的更新和渲染。每当我们修改DOM时,浏览器都需要重新计算样式、布局和绘制,这个过程被称为"重绘"(repaint)和"回流"(reflow),并且往往是昂贵且耗时的操作。
虚拟DOM通过在内存中构建一个轻量级的DOM树来解决这个问题。当应用程序的状态发生变化时,我们首先在虚拟DOM上进行修改,而不是直接操作真实DOM。通过比较新旧虚拟DOM的差异,我们可以确定哪些部分需要更新,并仅对这些部分进行实际的DOM操作。这种优化技术被称为"DOM Diffing"。
虚拟DOM的工作流程如下:
- 初始渲染:首次渲染时,将真实DOM转换为虚拟DOM。
- 状态变更:当应用程序的状态发生变化时,修改虚拟DOM树。
- 虚拟DOM Diffing:比较新旧虚拟DOM树的差异,找出需要更新的部分。
- 生成变更集:根据差异生成最小化的DOM操作序列。
- 应用变更:将变更应用于真实DOM,更新页面展示。
通过使用虚拟DOM,我们可以减少真实DOM操作的次数,并最大程度地减少重绘和回流的成本。这种优化能够显著提升性能,特别是在大型复杂的应用程序中,或是需要频繁更新的动态内容中。
← Array的变化侦测 Vue中的虚拟DOM →