什么是虚拟DOM?

virtual DOM 虚拟DOM,用普通js对象来描述DOM结构,因为不是真实DOM,所以称之为虚拟DOM。

虚拟 dom 是相对于浏览器所渲染出来的真实 dom而言的,在react,vue等技术出现之前,我们要改变页面展示的内容只能通过遍历查询 dom 树的方式找到需要修改的 dom 然后修改样式行为或者结构,来达到更新 ui 的目的。

这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要遍历整颗 dom 树,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查,这样一来查找 js 对象的属性变化要比查询 dom 树的性能开销小。

虚拟dom示例:

{
    sel: 'div',// 表述标签,如p、sapn
    data: {
        
    },
    children: undefined,
    text: 'virtual dom', //标签内的文本,
    ele: undefined,
    key: undefined
}

为什么要用虚拟DOM来描述真实的DOM呢?

创建真实DOM成本比较高,而如果用js对象来描述一个dom节点,成本比较低,另外我们在频繁操作dom是一种比较大的开销。所以建议用虚拟dom来描述真实dom。

这里有一些相关问题值得思考一下:

1.为什么操作真实DOM的成本比较高?

(1) dom 树的实现模块和 js 模块是分开的这些跨模块的通讯增加了成本

(2) dom 操作引起的浏览器的回流和重绘,使得性能开销巨大。

原本在 pc 端是没有性能问题的,因为pc端的计算能力强,但是随着移动端的发展,越来越多的网页在智能手机上运行,而手机的性能参差不齐,会有性能问题。
我们之前用jquery在pc端写那些商城页面都没有问题,但放到移动端浏览器访问之后会发现除了首页会出现白屏之外在其他页面的操作并不流畅。

2.浏览器收到一个html页面是如何解析成页面呈现给用户的呢?

(1) 解析html:会按顺序解析。浏览器有专门的html解析器来解析HTML,并在解析的过程中构建DOM树

(2)构建dom树:它和步骤(1) 是同步进行,可以理解为边解析边构建。

(3)构建呈现树renderTree:将dom树与css结合,也就是将样式应用到dom节点上

(4)布局:计算呈现树节点的大小和位置,这一位置是递归进行的。

(5)绘制:布局完成后,便是将呈现树绘制出来显示在屏幕上。

这个具体的解析过程可参考:https://www.cnblogs.com/dojo-lzz/p/3983335.html

3.什么是回流和重绘?

  • 回流 reflow:当呈现树renderTree中的一部分或全部因为尺寸、布局、隐藏等改变改重新构建,称之为回流。
  • 重绘:当呈现树renderTree中的一部分元素需要更新属性,而属性只会影响外观、风格而不影响布局,比如颜色、字体大小等,则称之为重绘。

我们之前用jquery时基本都是在操作dom。会频繁引起呈现树的重绘和回流,pc端处理能力还不错,但移动端性能就会很差。导致页面卡顿

虚拟DOM的作用和类库

  • 虚拟DOM作用

    • 可以维护视图和状态之间的关系
    • 复杂视图情况下提升渲染性能
    • 虚拟DOM除了可以渲染成DOM节点,还可以渲染到其他平台如ssr(nuxt.js/next.js)、原生应用(weex/rn)、小程序等,增加了跨平台能力
  • 开源库

    • snabbdom
      • vue 2.x就是使用的snabbdom并进行了一定的改造
      • 代码量少
      • 可以通过模块进行扩展
      • 源码使用ts开发
    • virtual-dom

思考

通过以上的分析,你觉得虚拟DOM的性能一定高于常规DOM吗?

答案是不一定,如果是简单页面操作起来虚拟DOM未必会获胜,这个具体的原因我们后面会有章节再来分析。

那你觉得使用了虚拟DOM就真的不操作dom元素了吗?其实不是的,只是减少用户操作dom,虚拟DOM在渲染的时候其实还是会操作dom的。

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐