什么是虚拟 dom?虚拟 dom 本质上就是一个普通的JS对象(mounted 中打印 this. _vnode 就是该对象内容),用于描述视图的界面结构 在vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟dom树,这也就意味着每个组件都对应一棵虚拟DOM树 vnode 是一个普通的 JS 对象,用于描述界面上应该有什么,比如: var vnode = { tag: "h1", children: [ { tag: undefined, text: "第一个vue应用:Hello World"} ]} 上面的对象描述了: 有一个标签名为 h1 的节点,它有一个子节点,该子节点是一个文本,内容为「第一个vue应用:Hello World」
为什么需要虚拟dom?在vue中,渲染视图会调用render函数,这种渲染不仅发生在组件创建时,同时发生在视图依赖的数据更新时。如果在渲染时,直接使用真实DOM,由于真实DOM的创建、更新、插入等操作会带来大量的性能损耗,从而就会极大的降低渲染效率。 因此,vue在渲染时,使用虚拟dom来替代真实dom,主要为解决渲染效率的问题。 对比创建js对象和真实 dom 对象效率:
结果:
创建一个真实的 dom 会伴随着创建许多的属性
虚拟dom是如何转换为真实dom的?在一个组件实例首次被渲染时,它先生成虚拟dom树,然后根据虚拟dom树创建真实dom,并把真实dom挂载到页面中合适的位置,此时,每个虚拟dom便会对应一个真实的dom。如果页面只会刷新一次,后续不会有数据更新等问题的情况下,用虚拟 dom 的方式是比直接显示真实 dom 效率低的。 如果一个组件受响应式数据变化的影响,需要重新渲染时,它仍然会重新调用render函数,创建出一个新的虚拟dom树,用新树和旧树对比,通过对比,找出差异,然后仅更新差异部分的虚拟dom节点,最后,这些更新过的虚拟节点,会去修改它们对应的真实dom 这样一来,就保证了对真实dom达到最小的改动。
模板和虚拟dom的关系vue框架中有一个compile(编译)模块,它主要负责将模板转换为render函数,而render函数调用后将得到虚拟dom。 编译的过程分两步: 1.将模板字符串转换成为AST(抽象语法树:用js树形结构来描述我们原始的代码;在线工具:https://astexplorer.net/) 2.将AST转换为render函数 vue 模板并不是真实的 DOM,它会被编译为虚拟 DOM <div id="app"> <h1>第一个vue应用:{{title}}</h1> <p>作者:{{author}}</p></div> 上面的模板会被编译为类似下面结构的虚拟 DOM { tag: "div", children: [ { tag: "h1", children: [ { text: "第一个vue应用:Hello World" } ] }, { tag: "p", children: [ { text: "作者:袁" } ] } ]} 如果使用传统的引入方式(script src="...vue.js "),则编译时间发生在组件第一次加载时,这称之为运行时编译。 如果是在vue-cli 的默认配置下,编译发生在打包时(npm run build ),打包之后就没有模板只有 render 函数了,这称之为模板预编译。 编译是一个极其耗费性能的操作,预编译可以有效的提高运行时的性能,而且,由于运行的时候已不需要编译,vue-cli在打包时会排除掉vue中的compile模块,以减少打包体积 打包时是否需要包含 下载地址: TypeScript中的函数 详解vue element plus多语言切换
|