DOM 和 Virtual DOM 分别是什么?它们之间的区别是什么?各自有什么优缺点?
我们一定需要Virtual DOM吗? React中是怎么做的?
是什么?
DOM(Document Object Modle):文档对象模型,本质是对 结构化文本 的一种抽象,在页面渲染出的每一个结点都是一个真实DOM
结构。
Virtual DOM: 以 JavaScript
对象形式存在的对 DOM
的描述,是对 HTML DOM 的一种抽象。
有什么区别
DOM | Virtual DOM | |
---|---|---|
操作时 | 会引起页面的排版和重绘 | 不会引起页面的排版和重绘 |
总损耗 | 真实DOM完全增删改 + 排版与重绘(较多节点) | 虚拟DOM增删改 + (与Diff算法效率有关)真实DOM差异增删 + 排版和重绘(仅更新必要部分) |
当使用 Virtual DOM 时,我们往往是频繁操作 Virtual DOM。然后一次性比较 真实DOM 和 Virtual DOM 之间的差异,并修改更新差异的部分到真实DOM (仅修改变更的真实DOM 节点)。
传统的原生api
或jQuery
去操作DOM
时,浏览器会从构建DOM
树开始从头到尾执行一遍流程。
当你在一次操作时,需要更新10个DOM
节点,浏览器没这么智能,收到第一个更新DOM
请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程。
而通过 Viratula DOM,同样更新10个DOM
节点,Virtual DOM 不会直接操作 DOM,而是将这10次更新的diff
内容保存到本地的一个js
对象中,最终将这个js
对象一次性attach
到DOM
树上,避免大量的无谓计算。
优缺点?
DOM | Virtual DOM | |
---|---|---|
优点 | 所见即所得的使用 | (1)高性能:使用Virtual DOM,能够有效避免真实DOM数频繁更新,减少多次引起重绘与回流,提高性能 (2)跨平台:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行 |
缺点 | (1)效率低:解析速度慢,内存占用过高 (2) 性能差:频繁操作真实DOM,易于导致重绘与回流 | (1) 在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化 (2) 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,速度比正常稍慢 |
React中是怎么实现的Virtual DOM?
在 React 中有一个特性被成为JSX(一种预发糖),它是js语法的一种扩展。
Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。
下面两种写法完全等价
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React 中提供 React.render 方法 用于将你创建好虚拟DOM
节点插入到某个真实节点上,并渲染到页面上(例子如下)
const element = <h1>Hello World</h1>
const root = document.getElementById('root')
ReactDOM.render(vDom, root)
总结:
1. React中提供一种语法糖JSX。 JSX`通过`babel 的方式转成`React.createElement`执行。
1. React.createElement 的返回值是一个对象,也就是虚拟DOM
一定需要Virtual DOM 吗?
Virtual DOM 真的渲染快?真的性能好吗?答案是不一定。
理智告诉我们,快慢好坏的评价往往取决于参照物。这个世界没有免费的午餐,diff的计算并不是没有开销的。
以上面<h1>
元素中的 "Hello world" 更名为 "Hello everybody"为例。
使用Virtual Dom 的变更步骤至少需要
- 检测节点,新旧VDOM中都是
<h1>
元素,保留相同的DOM节点 - 枚举新旧VDOM 上的所有属性,一一比较差异,检查是否需要增删改
- 将检测的变动属性更新到真实DOM 上
如果你直接精确的操作DOM,会节省前面的比较步骤,精准执行第三步。由此可见,精准操作DOM本身的性能一定是优于Virtual DOM的实现的。VDOM 在真实变更之前,还需要消耗内存计算Diff。
那么问题来了,为什么很多前端框架还是使用Virtual DOM?
理解虚拟DOM不是一个特性很重要。它是达到 声明性的、状态驱动的UI开发
的一种手段。
精准操作DOM的性能确实优于VDOM,但是精准操作本身与程序员的水平本身息息相关,我们很难保证团队内的每个成员水平都保持在高水平。所有的编码都能优化到对最小成本的操作真实DOM。
虚拟DOM很有价值,因为它允许您构建应用程序,而无需考虑状态转换,性能通常足够好,这样开发者在操作DOM更新的时候心智负担就会很小。这意味着更少的错误代码,进而在整体程序上提高性能和渲染效率。
除此之外,VDOM 因为是对DOM的抽象,天然就具有跨端的能力。
但事实证明,我们也可以在不使用虚拟DOM的情况下实现类似的编程模型。
总结
- 不需要将Virtual DOM 作为一个特性,它只是一种达到
数据驱动UI开发
的一种手段。它是对DOM的抽象描述,提供了统一管理DOM的能力,开发者不再需要记住复杂的DOM操作,不需要关心数据变动之后的更新,也不再要求每个开发者都能做到最优操作DOM,进而提升项目整体的性能和渲染效率 - 上来就说过,
Virtual DOM
是对 DOM 的一种描述,本质是 javascript 对象,或者编译为其它语言的对象,那么换一种宿主环境,就可以让vdom
在新的平台继续使用,比如去进行SSR(Server Side Render)
,或者很出名的React Native
。
参考文献