当前位置: 首页 > Web前端 > vue.js

你知道Vue3中的编译优化吗?

时间:2023-03-31 18:38:24 vue.js

前言与Vue2相比,Vue3通过各种编译优化大大提升了Vue的整体性能,这也使得Vue3在编译和更新阶段实现了更快的速度提升!一起来看看吧!什么是编译器优化?编译优化是指编译器在将模板(template)编译成渲染函数(render)的过程中,尽可能提取关键信息,从而达到生成最优代码的过程。你为什么需要它?传统的Diff算法会有很多无意义的比较操作。在比较新旧虚拟DOM的时候,总是需要按照虚拟DOM的层级结构“逐层”遍历,然后一些内容的遍历比较就完全没有用了。必要的,例如:{{text}}

唯一可能的变化是

标签中的文本值,当当响应式数据文本被修改时,最高效的更新方式是直接更新

标签对应的文本内容。但是对于传统的Diff算法,会先根据render函数生成一个新的虚拟DOM,然后比较新旧虚拟DOM方法:比较div节点,以及该节点的属性和子节点与p节点,将该节点的属性和子节点与p节点的文本节点进行比较,发现文本节点发生了变化,于是更新文本节点编译思路思路来源就是跳过这些无意义的pair操作,进一步提高Vue中Diff算法的比较性能:模板结构比较稳定,关键信息(如:标记静态节点和动态节点)尽可能在编译阶段提取出来在关键信息上,由编译器直接生成对应的原生DOM操作代码,减少了生成虚拟DOM的性能消耗,有助于提高初始化ren的速度dering实验性的新编译策略从理论上来说,在某些情况下确实不需要虚拟DOM,(即NoVirtualDOM),但仍然选择在Vue.js3中保留虚拟DOM,并承担由此带来的性能开销通过它,主要考虑渲染功能的灵活性和Vue.js2的兼容性。如果大家有兴趣,可以了解一下Vue未来会提供的一些新特性,但这不是本文的核心内容。StateofVue2022-游玉溪Vue3编译优化标记动态节点。标记动态节点后,后续渲染器更新old阶段,可以直接基于动态节点集合,实现动态节点的定向更新或定向更新。patchFlag属性由编译器编译。如果它判断当前节点属于动态节点,就会为这个vnode节点标记patchFlag,同时也只需要添加一个patchFlag属性,patchFlag属性对应的是该值表示当前动态节点的类型,如:数字1:表示节点是动态textContent数字2:表示节点是动态cass绑定数字3:表示节点是动态样式绑定...dynamicChildren属性dynamicChildrenproperty值对应一个数组,里面存放的是具有patchFlag属性的vnode节点,具有dynamicChildren属性的vnode节点称为block,即Block.Block节点。Block本质上也是一个虚拟DOM节点。只是它比普通的虚拟节点多了一个dynamicChildren属性来存储动态子节点。一个Block不仅可以收集其直接的动态子节点,还可以收集所有的动态子节点,renderer后续的更新操作都会以Block为更新维度进行处理。什么样的节点会成为区块节点?所有模板的根节点都是带有v-if指令的节点。带有v-for指令的节点。模板中由Frament节点包裹的多个根节点。v-if和v-for指令会导致模板结构在更新前后不稳定,但是由于v-for指令渲染了一组子节点,为了更好的表示这组子节点,所以需要使用Fragment节点来表达v-for指令的渲染结果,将其作为Block节点使用。StaticpromotionStaticpromotion的目的是尽量减少更新时创建虚拟DOM带来的性能开销和内存占用。没有静态提升带来的问题,通常是响应式数据发生变化时,会重新执行渲染函数,生成新的虚拟DOM。DOM节点,显然不需要重新创建纯静态的虚拟节点,会带来一定的性能开销。该方案可以在编译阶段将纯静态节点提升到渲染函数外,在渲染函数内部保留对静态节点的引用,即当响应式数据变化导致渲染函数重新执行时,静态虚拟节点不会重新创建,这样old就可以避免重复创建静态节点的虚拟DOM带来的性能开销。值得注意的是,静态提升是以树为单位的。毕竟不可能对每个小的静态节点都进行静态提升,这样会增加渲染函数外存储静态节点对应的变量个数,也会占用一定的内存。预串化是基于静态提升的,可以继续沿用预串化的优化方式,即直接以树为单位进行升级。根据DOM操作,直接将内容转换成相应的字符串格式。预字符串化的优势在于:大块的静态内容可以直接通过innerHTML设置,在初始渲染时有一定的性能优势,降低创建虚拟节点的成本。通过缓存内联事件处理程序来减少内存使用。不缓存内联事件处理器导致的问题在模板事件处理器中,对于一些简单的更新操作,内联事件处理器通常写在模板中,例如:===>functionrender(ctx){returnh(Com,{//内联事件处理器onChange:()=>ctx.c=ctx.a+ctx.b})}显然,当render函数被重新执行时,一个新的props会为Comp组件创建对象,onChange事件也是一个新函数,会导致渲染器更新Comp组件,造成额外的性能开销解决方法是将第二个参数缓存数组传递给render渲染函数,而这个缓存数组来自于组件实例,所以可以将内联事件处理器添加到缓存数组中进行缓存。当渲染函数重新执行创建时,使用虚拟DOM时,先从缓存中读取对应的事件处理函数,避免事件处理函数被重新创建,导致Comp组件无用的更新。v-once缓存虚拟DOMVue.js2和Vue.js3都支持v-once指令,当前编译器遇到v-once指令时,会使用上面提到的缓存数组来缓存v-once指令的全部或部分执行结果渲染功能。v-once的优点是避免了组件更新时重新创建虚拟DOM带来的性能开销。因为虚拟DOM被缓存了,所以更新时不需要重新创建它,避免无用的Diff开销。这是因为v-once标记的虚拟DOM树会被父Block节点收集。最后,以上就是本文的全部内容。希望对大家有所帮助。帮助!!!本文参加了SegmentFault思维写作挑战赛,欢迎正在阅读的你加入。