Why do we need virtual dom?

What is the role of virtual dom?

Posted by My on May 30, 2022

为什么我们需要虚拟 DOM?也许之前我们会回答,虚拟 DOM 是为了提高性能,减少 DOM 操作,提升用户体验。 但是,svelte 并没有使用虚拟 DOM,而是直接操作真实的 DOM,并且效率还更高了。确实我们减少了真实 DOM 的操作,但如「vue」和「react」,最后还是得去操作真实的 DOM。

所以看来,使用虚拟 Dom 好像并不是为了提高性能。那我们从其他层面来分析下这个问题。

框架设计

首先框架就是这么设计的,要求是「数据驱动模式」,数据一发生变化,其它的一些内容就要发生变化,如视图页面的更新。

那么最理想的设计是,数据一发生变化,就直接定位到真实的 DOM。 我们这里这么理解,在原生 html 中,我们通过模版字符串,直接修真的 DOM。或者说某个数据变化,我们直接修改这个 DOM 的 innerText 。这种方式是效率最好的,没有弯弯绕绕的东西。

但是,对于 vue 和 react 来说,他们的框架设计达不到这个要求,没办法精确定位到具体的 DOM 节点。也就是说颗粒度没那么细,只能精确到组件。也就是说,在 vue 和 react 中,数据一发生变化,视图页面的更新,都是通过重新渲染整个组件树来实现的。那就会造成一个问题,如果组件有 10000 个 DOM,那么每次数据变化,都要重新渲染整个组件树,这显然是不可接受的。

「所以,为了提高性能,vue 和 react 都使用了虚拟 DOM。」 也就是说,没办法精确到具体的 DOM 节点,只能渲染出一个虚拟的 DOM 树,然后再把这个虚拟的 DOM 树映射到真实的 DOM 上。

解耦运行环境

「虚拟 DOM」的另一个作用,就是解耦运行环境。因为虚拟 DOM 并不是真实的 DOM,所以它可以被渲染到任何地方。比如,在浏览器环境中,我们可以把虚拟 DOM 渲染到浏览器的 DOM 上,然后通过浏览器的 API 来操作真实的 DOM。但是在框架设计之初,并没有规定只能在浏览器环境中使用。vue 和 reat 是希望还能在小程序或者移动端运行,但是移动端是原生组件,所以就不能绑定到真实的 DOM 上。所以,虚拟 DOM 让我们可以把渲染和操作 DOM 的代码解耦,从而让我们可以更方便地在不同的运行环境中使用。