为什么我们需要虚拟 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 的代码解耦,从而让我们可以更方便地在不同的运行环境中使用。