javascript我爱编程

virtual dom的理解

2018-04-19  本文已影响16人  技术与健康

本文主要是自己对https://www.zhihu.com/question/31809713一贴中各位大神分享的学习记录,不一定对,希望通过不断学习加深理解。

问题:为什么需要virtual dom?

先的说说virtual dom 是什么,virtual dom就是原生dom在内存中的js对象映射,但不是完全复制,它比真实dom节点在属性上简化了,也就是说是更加轻量级,相当于是数据和原生dom的一层缓存。

在司徒正美的回复中有例子。这里就不罗列了。

之前一直有一种说法,说是virtual dom操作比原生dom快。

先说原生dom,dom发生变化后,就需要重新布局,绘制,渲染等等,一般说的原生dom慢,主要是说重新渲染,绘制的消耗。

对于初始渲染,其实没有大的差别,毕竟virtual dom最终也是要渲染成原生dom的。主要的差异体现在后续的变更上。

我们可以比较一下 innerHTML vs. Virtual DOM 的重绘性能消耗:

innerHTML:  render html string O(template size) + 重新创建所有 DOM 元素 
O(DOM size)

Virtual DOM: render Virtual DOM + diff O(template size) + 必要的 DOM 更新 O(DOM change)。

但是如上面讲到的,主要的消耗在dom的重绘,渲染,相比之下js diff的计算,虽然会耗一部分时间,但是其整体占比不多,因此也还不错。像react还提供了shouldComponentUpdate用来优化这种场景,因此可以说使用了Virtual DOM,在大部分场景下性能还是可以接受的。

“可以看到,innerHTML 的总计算量不管是 js 计算还是 DOM 操作都是和整个界 面的大小相关,但 Virtual DOM 的计算量里面,只有 js 计算和界面大小相关,DOM 操作是和数据的变动量相关的。前面说了,和 DOM 操作比起来,js 计算是极其便宜的。这才是为什么要有 Virtual DOM:它保证了 1)不管你的数据变化多少,每次重绘的性能都可以接受;2) 你依然可以用类似 innerHTML 的思路去写你的应用”

Virtual DOM和MVVM

相比起 React,其他 MVVM 系框架比如 Angular, Knockout 以及 Vue、Avalon 采用的都是数据绑定:通过 Directive/Binding 对象,观察数据变化并保留对实际 DOM 元素的引用,当有数据变化时进行对应的操作。MVVM 的变化检查是数据层面的,而 React 的检查是 DOM 结构层面的。

MVVM 实现的一个共同问题就是在列表渲染的数据源变动时,尤其是当数据是全新的对象时,如何有效地复用已经创建的 ViewModel 实例和 DOM 元素。假如没有任何复用方面的优化,由于数据是 “全新” 的,MVVM 实际上需要销毁之前的所有实例,重新创建所有实例,最后再进行一次渲染!这就是为什么题目里链接的 angular/knockout 实现都相对比较慢。相比之下,React 的变动检查由于是 DOM 结构层面的,即使是全新的数据,只要最后渲染结果没变,那么就不需要做无用功。 Angular 和 Vue 用了 track by $index 用来优化这种场景。

性能

Virtual DOM从来都不是单独存在的。Virtual DOM、脏检查 MVVM、数据收集 MVVM 在不同场合各有不同的表现和不同的优化需求。Virtual DOM 为了提升小量数据更新时的性能,也需要针对性的优化,比如 shouldComponentUpdate 或是 immutable data。

其实如果一定要说这个为什么? 那就是Virtaul DOM是作为一定场景下,解决性能问题提出来的解决方案。

他山之石

虚拟DOM快在哪里

然后,js计算肯定要比DOM操作快啊,每次DOM操作都很有可能引起回流(Reflow)和重绘(Repaint)啊。当然浏览器也不傻,不是你每次操作DOM浏览器都重绘一次,一般浏览器会按照时间或次数间隔进行DOM操作的批处理。那问题来了,到底是浏览器优化后的DOM批处理快,还是React的虚拟DOM+优化diff算法快。这个我没有测试过,根据博客上内容,React的优化更人性化、也更快。速度快肯定是虚拟DOM的一个优点,另外一点,浏览器对DOM操作批处理的主动权不在前端人员手中,React将这种批处理的时机选择交到了我们手中,看我们什么时候想render页面。这个和AJAX+回调带来的问题一样,当我们发送一个AJAX,然后指定一个回调函数时候,对回调里代码的控制权就交给浏览器了,所以前端人员常常感觉AJAX不可控,不知道回调什么时候执行完了,页面一大堆flag。
https://blog.csdn.net/qiqingjin/article/details/51804138

上一篇下一篇

猜你喜欢

热点阅读