虚拟DOM同样也是操作DOM,为啥说它快?

我踮脚眺望旧时光
  • 40

虚拟DOM同样也是操作DOM,为啥说它快?

回复
阅读 14.5k
10 个回答
✓ 已被采纳

你的知道浏览器的虚拟DOM与真实DOM的区别(注意:需不需要虚拟DOM,其实与框架的DOM操作机制有关):

  1. 虚拟DOM不会进行排版与重绘操作

  2. 虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分(注意!),最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗

  3. 真实DOM频繁排版与重绘的效率是相当低的

  4. 虚拟DOM有效降低大面积(真实DOM节点)的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部(同2)

使用虚拟DOM的损耗计算:

总损耗 = 虚拟DOM增删改 + (与Diff算法效率有关)真实DOM差异增删改 + (较少的节点)排版与重绘

直接使用真实DOM的损耗计算:

总损耗 = 真实DOM完全增删改 + (可能较多的节点)排版与重绘

总之,一切为了减弱频繁的大面积重绘引发的性能问题,不同框架不一定需要虚拟DOM,关键看框架是否频繁会引发大面积的DOM操作

虚拟dom是同样操作dom

贴一段snabbdom Readme的话

Virtual DOM is awesome. It allows us to express our application's viewas a function of its state. But existing solutions were way way too bloated, too slow, lacked features, had an API biased towards OOP and/or lacked features I needed.

把dom树抽象成数据对象
virtual dom 它可以使我们操作这块的数据对象
用数据对象来呈现dom树
在每次视图渲染的时候patch取得最优。
这种做法在我们小量地修改dom是很有好处的。
而在修改大量的数据的时候,不见得能快很多。甚至要慢
而virtual dom还有一个很大的作用是
简化dom操作,让数据与dom之间的关系更直观更简单
不选定场景的讨论都是耍流氓
以上 鄙人一些拙见。望与诸君共探讨

下面是知乎的一个近似链接
网上都说操作真实 DOM 慢,但测试结果却比 React 更快,为什么?

只能说 虚拟DOM 只是减少了一些情况下, 对真实DOM操作的 次数.

虚拟DOM只是个 JavaScript object

它会在 对比 后再选择更新哪些DOM, 而不会像有些时候, 全部删除再重建.

获取/修改 大量DOM元素的时候,就会先在 虚拟DOM 里 取值 对比.

然而在某些情况下, 虚拟DOM 也会比 原生DOM 更慢.

因为其数据全部在内存中,只有js引擎参与其中

而真实dom会有浏览器渲染层在其中,这个慢

这样说吧。

有一个 DOM 结点 d

<div id="d">
    <h1 title>{{ title }}</h1>
    <div class="intro-container">
        {{ intro }}
        <p intro>{{ welcome }}</p>
    </div>
</div>

上述模版对应的数据是:

var data = {
    title: 'just title', 
    intro: 'it is a title', 
    welcome: 'welcome welcome'
}

框架已经完成了对数据的绑定(例如 Vue),因此在data上的属性们被重写的时候,会触发 setter,这时候有两个选择:

  1. 暴力的用 innerHTML 赋值改变

  2. 利用某种方法精确修改 DOM

前者简单可行,但是性能不太好,因为 DOM 操作开销很大。在这种情况下,只要一个属性被重写,整个模版都会被重新渲染,不太好。

后者可以采用虚拟 DOM ,虚拟 DOM 跟普通 DOM 类似,在需要渲染的时候,先在虚拟 DOM 渲染好,然后跟当前普通的 DOM diff 一下,得出需要修改的变化点,然后进行精准的修改,以提升性能。

以上是我的理解。

先举例子:

Virtual DOM :

var element = {
    type: 'h1',
    attributes: [],
    children: []
};
console.log(element);
// 三个

DOM:

var element = document.createElement('h1');
console.log(element);
// 70-80 个属性。

1: 从空间复杂度上来说,减少的不是一点点,如果它是一个树的时候,你可想而知它空间复杂度的问题。
2: 时间复杂度: diff 。减少真实Dom的CRUD次数;注意,这里对真实DOM的操作上的并没有减少,但减少了操作次数,还有就是innerHTML替代createElement
3: immutable;

虚拟dom是在内存中维护的dom树,是在实体dom之上的一层抽象。有了这层抽象,不管是查询操作还是修改操作,都是先操作内存中的虚拟dom,在这个过程中可以做很多优化,从而减少对实体dom的操作。举两个例说明,1. 查询一个text标签的值,可以直接从虚拟dom中查找得到,根本不需要查询实体dom。2. 在一次操作中,要修改列表中的两条记录,要修改的元素会先把变更同步到虚拟dom上,然后根据最新的虚拟dom,一次性渲染出最终的实体dom,如果没有虚拟dom,两条记录的修改至少要对应两次对实体dom的操作,显然操作实体dom越频繁,网页速度越慢。

最主要的原因: 假设需要将ui的状态从vdom1变成vdom2, 那么 (比较vdom2 - vdom1 并把不同点更新到dom) 比 (用vdom2完全重建dom) 快

多一层vdom还可以用来缓存dom状态, 事件代理之类, 不过这不是最重要的因素

其实虚拟DOM是牺牲了cpu来成全速度。

宣传栏