JS操作真实DOM的代价
用我们传统的开发模式,原生JS或JQ操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个DOM节点,浏览器收到第一个DOM请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。例如,第一次计算完,紧接着下一个DOM更新请求,这个节点的坐标值就变了,前一次计算为无用功。计算DOM节点坐标值等都是白白浪费的性能。即使计算机硬件一直在迭代更新,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。
为什么需要虚拟DOM,它有什么好处?
Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
虚拟DOM 的作用
要想回答上面那个问题,真的不要仅仅以为虚拟 DOM 或者 React 是来解决性能问题的,好处可还有很多呢。下面我总结了一些虚拟 DOM 好作用。
- Virtual DOM 在牺牲(牺牲很关键)部分性能的前提下,增加了可维护性,这也是很多框架的通性。
- 实现了对 DOM 的集中化操作,在数据改变时先对虚拟 DOM 进行修改,再反映到真实的 DOM中,用最小的代价来更新DOM,提高效率(提升效率要想想是跟哪个阶段比提升了效率,别只记住了这一条)。
- 打开了函数式 UI 编程的大门。
- 可以渲染到 DOM 以外的端,使得框架跨平台,比如 ReactNative,React VR 等。
- 可以更好的实现 SSR,同构渲染等。这条其实是跟上面一条差不多的。
- 组件的高度抽象化。
既然虚拟 DOM 有这么多作用,那么上面的问题,Vue 采用虚拟 DOM 的原因是什么呢?
Vue 2.0 引入 vdom 的主要原因是 vdom 把渲染过程抽象化了,从而使得组件的抽象能力也得到提升,并且可以适配 DOM 以外的渲染目标。 Vue 的理念问题
虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种 GUI。
虚拟 DOM 的缺点
- 首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,会比 innerHTML 插入慢。
- 虚拟 DOM 需要在内存中的维护一份 DOM 的副本(更上面一条其实也差不多,上面一条是从速度上,这条是空间上)。
- 如果虚拟 DOM 大量更改,这是合适的。但是单一的,频繁的更新的话,虚拟 DOM 将会花费更多的时间处理计算的工作。所以,如果你有一个DOM 节点相对较少页面,用虚拟 DOM,它实际上有可能会更慢。但对于大多数单页面应用,这应该都会更快。
1 | const $app = document.querySelector('.app'); |
1 | const activeProfile = <div class="main-01"> |
再次审视Virtual DOM,可以简单得出如下结论:
- Virtual DOM 在牺牲部分性能的前提下,增加了可维护性,这也是很多框架的通性
- 实现了对DOM的集中化操作,在数据改变时先对虚拟DOM进行修改,再反映到真实的DOM中,用最小的代价来更新DOM,提高效率
- 打开了函数式UI编程的大门
- 可以渲染到DOM以外的端,比如ReactNative