官方文档中说vue3在 客户端渲染效率比vue2提升了1.3~2倍, SSR渲染效率比vue2提升了2~3倍,那么究竟是怎么提升的呢?
在 vue3项目中的package.json文件中,可以看到这个 @vue/compiler-sfc,它是用来解析(.vue)文件的。在解析的时候,下面的静态节点会被提升。
//vue2的静态节点
render(){
createVNode("h1",null,"Hello World")
//...
}
//vue3的静态节点
const hoisted = createVNode("h1",null,"Hello World")
function render(){
//直接使用hoisted
}
静态属性会被提升
{{user.name}}
以上代码,div的节点虽然是动态的,但是class属性是静态的, 所以会将class属性提出
const hoisted = {class:"home"};
function render(){
createVNode("div",hoisted,user.name)
}
class被提出后,可以反复重用hoisted 对象,减少内容占用。而vue2 每次都会重建一个对象。
当编译器遇到大量的且连续的静态内容时,会将其编译为一个普通字符串节点。
编译结果如下:
const _hoisted_1 = /*#__PURE__*/
_createStaticVNode("", 1)
在vue3会将事件缓存起来,在执行的时候会将事件编译成函数,缓存在_cache对象中。看_cache中有这个函数,有就直接返回,没有把这个函数初赋值给_cache。
编译结果如下 :
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(),
_createElementBlock("div", null, [_createElementVNode("button", {
onClick: _cache[0] || (_cache[0] = $event=>($setup.count++))
}, "增加")]))
}
Block Tree是一个非常大的更新,是为了解决新旧节点对比的效率问题。vue2在对比新旧数的时候,并不知道哪些节点时静态的,哪些节点时动态的,因此只能一层一层比较,这就浪费了大部分时间在对比静态节点上。
而vue3对节点进行了标记
lora
{{ count }}
{{ count }}
从上面结果可以看出,对静态节点的标识是 -1 ,/* HOISTED */静态,动态节点的标识是 1 ,/* TEXT */ 动态,并且会把所有动态节点提取到根节点。更新的时候直接找到根节点(Block节点),然后找到动态节点进行对比。
vue2在对比没一个节点时,并不知道这个节点哪些相关信息会发生变化,因此只能将所有信息依次对比。
在vue3中,根据各个节点的不同的特点,打上不同的PatchFlag,在patch 的时候就会根据PatchFlag进行比较,不会进行全量比较。
从上面的结果可以看出:
以上为vue3效率提升的总结,如有不同见解请留言,谢谢。