写点什么

一文带你了解 vue 之虚拟 dom

用户头像
法医
关注
发布于: 2021 年 06 月 09 日
一文带你了解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 的配置。


😊 好了, 以上就是我的分享,大家对于虚拟 dom 还有其它理解的话可以在评论区讨论鸭~


记得点赞 👍 支持一下哦~ 😘

发布于: 2021 年 06 月 09 日阅读数: 867
用户头像

法医

关注

公众号@前端猎手 2020.07.17 加入

喜欢用写作记录自己技术成长过程

评论

发布
暂无评论
一文带你了解vue之虚拟dom