浅谈Virtual DOM

What

先来看下Wikipedia在React介绍中对Virtual DOM的说明:

Another notable feature is the use of a “virtual Document Object Model”, or “virtual DOM”. React creates an in-memory data structure cache, computes the resulting differences, and then updates the browser’s displayed DOM efficiently. This allows the programmer to write code as if the entire page is rendered on each change, while the React libraries only render sub components that actually change.[1]

说的简单一些,就是 在JS中对DOM树结构的一组模拟数据

Why

首先明确一个问题,Virtual DOM相较原生DOM的速度要慢(在Quora[2]中有相关的讨论)。

在浏览器中,DOM的实现和ECMAScript的实现是分离的。比如 在IE中,ECMAScrit的实现在jscript.dll中,而DOM的实现在mshtml.dll中;在Chrome中使用WebKit中的 WebCore处理DOM和渲染,但ECMAScript是在V8引擎中实现的,其他浏览器的情况类似。所以通过JavaScript代码调用DOM接 口,相当于两个独立模块的交互。相比较在同一模块中的调用,这种跨模块的调用其性能损耗是很高的。[3]

那么为什么还要使用Virtual DOM来进行速度优化呢?这就要从浏览器对页面的渲染说起。

浏览器渲染流程

如图中所示,浏览器的渲染主要包括[4]
->资源加载(loading)
->解析和构建DOM树(parse and construct DOM tree )
->构建渲染树(construct render tree)
->布局(layout)
->绘制(paint)
->等后续操作

应用开发时,主要影响性能的是DOM操作所引起的重构(reflow)和重绘(repaint)。而且重构相较重绘的影响更大。其原因是浏览器中DOM树的树形结构检索编辑以及绘图API的实现方式导致。

随着用户体验要求的提高,前端实现逻辑亦趋复杂,导致了Web Api以及jQuery等类库,已无法再满足开发需求,各种新的解决方案随之提出:

- 理论:SPAMVCMVVM工程化
- 框架:AngularReactVue

项目复杂度的增加,导致数据之间,数据和展示之间的关联性也随之增强。在数据改变时,需要改变关联的页面展示,及相关联的其他数据,如果需要开发人员自行处理,那么其工作量是庞大且易出错的。因此如何在数据更新时,及时更新对应的页面元素及关联数据则是问题所在,Virtual DOM也应运而生。

Tip: DOM树本身的操作和运算并不慢,慢的是在DOM树改变时,引起的浏览器的repaint和reflow

How

那么Virtual DOM的基本原理是什么呢?
Virtual DOM和浏览器渲染

从图中可以看到,Virtual DOM所优化的目标是reflowrepaint阶段。

Virtual DOM是存储在浏览器内存中隶属于JavaScript的数据结构,与实际DOM节点是一一对应的关系。可以看做是夹在应用程序和实际DOM间的中间层。

一般情况下,有数据变化时,框架会通过diff算法[5],确定需要变化的DOM节点,如下图所示:
diff算法

但此时,真正的DOM节点并没有改变。针对不同框架的实现可能不同,但通俗来讲,都会有执行的周期,在准备期间记录需要变化的DOM节点,在执行前计算出最小的更新视图。待达到执行更新时,调用Web API进行批量DOM更新,最终使浏览器的重构和重绘代价最小。但是需要注意的是,在进行变动DOM节点比较和确定时,也是需要计算量的。

可以说Virtual DOM是作为应用进行实际DOM操作的中间件,它的存在,将框架的实现逻辑和底层DOM的数据节点进行了解耦,因此降低了多平台开发的代价。于此同时,对于上层,Virtual DOM可以提供更多的自定义API,已提供对DOM节点的更丰富的操作。

在这里仅仅是对Virtual DOM进行了最浅显的了解。如果更深入的话,可以了解diff算法[6]的实现原理,和不同框架的不同方式。这里[7]是简易实现Vue框架的一片博客,感兴趣的可以自行参考。

引用

1. Wikipedia
2. Quora
3. 前端页面卡顿、也许是DOM操作惹的祸?
4. 前端必读:浏览器内部工作原理
5. Change And Its Detection In JavaScript Frameworks
6. 手把手教你从零写一个简单的 VUE
7. 关于react diff 算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值