一文带你了解 vue 之虚拟 dom

在面试的过程中,可能也会被问到对虚拟 dom 的理解,像这种面试题是比较宽泛的,面试官想知道你到底知道多少?既然是理解,那就只能是知无不言言无不尽,尽量组织下语言多说点,这样才显得专业素养比较高,接下来,我来谈谈自己的理解,切记不要去背,一定要理解之后,用自己的语言来描述出来。

我们可以从以下四个方面来回答:

什么是虚拟 dom

虚拟 dom 本质上就是一个普通的 JS 对象,用来描述视图上应该有哪些界面结构,并不生成界面。我们可以在生命周期 mounted 阶段打印一下this._vnode,如下:

描述了标签为div有哪些属性、以及有哪些子元素等等,它通过普通的 js 对象这种形式来描述页面上应该有哪些东西,但并不会生成界面。

在 vue 中,每个组件都有一个 render 函数,每一个 render 函数都会返回一个虚拟 dom 数,这也就意味着每个组件都对应一棵虚拟 DOM 树。

为什么需要虚拟 dom

这个主要是由 vue 框架结构所决定的,在 vue 中,渲染视图会调用 render 函数,这种渲染不仅发生在组件创建时,而且还会发生在依赖的数据更新的时候。前端培训如果在渲染时,直接使用真实 DOM,由于真实 DOM 的创建、更新、插入等操作会带来大量的性能消耗,从而会极大的降低渲染效率。

示例:对比创建 js 对象和创建真实 dom 对象进行用时对比

<script>      var times = 10000000;//次数为1000万次      //js对象      console.time(`js object`);      for (var i = 0; i < times; i++) {        var obj = {};      }      console.timeEnd("js object");      //真实dom对象      console.time(`dom object`);      for (var i = 0; i < times; i++) {        var obj = document.createElement("div");      }      console.timeEnd("dom object");</script>

运行结果

从结果看,js 对象用时 150ms,而真实 dom 用时将近 7s 了,这个还不算插入到页面中导致的重绘重排时间,非常恐怖!

因此,vue 在渲染时,使用虚拟 dom 来代替真实 dom,主要为解决渲染效率的问题。那光有虚拟 dom 也不能够啊,那页面咋显示呢?总不能是无字天书吧!接下来就是第三个方面了

虚拟 dom 如何转换为真实 dom

在一个组件实例第一次被渲染的时候,它会先生成虚拟 dom 树,然后根据虚拟 dom 树创建真实 dom,最后会把真实的 dom 挂载到页面中合适的位置,所以说,创建真实的 dom 这一步是少不了的,只能说尽量的少创建,如果说页面只需要渲染一次,后面的数据变化都不重新渲染页面,这时 vue 的效率跟直接操作 dom 效率相比其实是更加低的,因为它比直接操作 dom 还多一个步骤:创建虚拟 dom。第一次 vue 渲染效率是不高的,但是后续就不一样了。

如果一个组件受到响应式数据变化的影响,需要重新渲染时,它仍然会重新调用 render 函数,创建一个新的虚拟 dom 树,这时会用新虚拟 dom 树(newVnode)和旧虚拟 dom 树(oldVnode)进行对比,通过比对,vue 会找到最小更新量,然后更新必要的虚拟 dom 节点,最后,这些更新过的虚拟节点会去修改它们对应的真实 dom。这样一来就保证了对真实 dom 的操作达到了最小的改动。

比对过程其实是用到了一个算法,叫patch,它可以判断出哪些节点发生了变化,从而只对发生变化的虚拟 dom 节点进行更新,关于 patch 我会专门出一篇文章谈谈自己的看法。

模板和虚拟 dom 的关系

vue 框架中有一个compile模块,它主要负责将模板转换为render函数,而 render 函数调用后得到虚拟 dom。

编译过程分为两步:

  1. 将模板字符串转换为 AST(Abstract Syntax Tree,抽象语法树)

  2. 将 AST 转换为 render 函数

  • 如果使用传统的引入方式(使用 script 标签引入 vue.js),编译时间发生在组件第一次加载时,被称为运行时编译

  • 如果是在 vue-cli 默认配置下,编译发生在打时,被称为模板预编译

编译是一个极其耗费性能的操作,预编译可以有效的提高运行时的性能,而且,由于运行时已经不需要编译,vue-cli 在打包时会排除掉 vue 中的 compile 模块,这样可以减少打包体积。

模板的存在,仅仅只是为了我们更加方便的书写界面代码,vue 最终运行的时候,最终需要的是 render 函数,而不是模板,这里要注意的是 vue 它是不认识模板的,模板是 vue-cli 预编译所需要的,它最终会将模板编译成 render 函数提供给 vue 正常运行。因此模板中的各种语法,在虚拟 dom 中都是不存在的,它们都会变成虚拟 dom 的配置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值