什么是虚拟DOM
在vue中,render函数创建虚拟DOM树,每个组件都有一个rende函数,所以每个组件都对应一颗虚拟DOM树(VNode),
VNode下的children属性就是记录该组件template标签里有哪些子元素(或者子组件),子元素里面的子元素形成树形结构,
虚拟DOM也是一个普通的JS对象,用于描述视图的界面结构,并不会显示界面,VUE中虚拟DOM像下面这样
为什么要有虚拟DOM
主要DOM元素的更新,删除导致页面的重排重绘会耗费大量的损耗,但是虚拟DOM的更新,删除,vue在处理的时候会最大化的节省性能, 解决渲染效率的问题
虚拟DOM如何转换成真实DOM
在一个组件实例初次被渲染时,先是调用render函数生成虚拟DOM树,然后根据虚拟DOM树创建真实DOM,再把真实DOM挂载到页面合适的位置,所以虚拟DOM创建真实DOM的操作是少不了的,并且每一个虚拟DOM会对应一个真实DOM
如果组件受响应式数据变化的影响,要重新渲染时,仍然会重新调用render函数,创建一个新的虚拟DOM树,用新树和旧树做对比,通过对比,vue会找到最小更新量,然后更新必要的虚拟DOM节点,最后这些更新过的虚拟节点,会去修改他们对应的真实DOM(patch算法),就保证了对真实DOM最小的改动
模版(template)与虚拟DOM的关系
template本质上是一个字符串,组件实例的一个配置template:``,template的存在,只是为了让开发人员更加方便的书写代码
VUE中只有通过render函数才能得到虚拟DOM树,vue中编译模块complier会将模版转换为render函数,render函数调用后得到虚拟DOM
编译分为两步
1 模版字符串转换成AST
2 AST转换成为render函数
啥是编译:模版转换为render函数,编译是一个极其耗费性能的活儿
编译又分为两种,运行时编译/模版预编译
运行时编译:使用script标签引入vue文件或者脚手架中vue.config.js配置runtimeCompiler:true就是运行时编译,结果会造成编译时间在组件第一次加载时就运行,会把模版转换为render函数
预编译:脚手架中默认配置runtimeCompiler:false,执行的是模版预编译,编译发生在打包才执行