根据官方介绍
客户端渲染效率比Vue2提升了2-3倍。 SSR渲染效率比Vue2提升了2-3倍。
那么具体来讲,Vue3在那些方面改进导致了效率的提升?
静态提升
- 静态节点会被提升
- 元素节点
- 没有绑定动态内容
Vue2中,会将模块template预编译为一个render函数。
// Vue2 的静态节点
render() {
createVNode('h1', null, 'content')
}
// Vue3的静态节点
const hoisted = createVNode('h1', null, 'content')
render() {
// 使用hoisted即可
}
对于静态节点(没有动态绑定任何值,一个单纯的元素标签),Vue2中每调用一次render函数都会去编译静态节点。但在Vue3中,既然静态节点是不会做改变的,那么直接将静态节点提出render函数外,这样该静态节点只编译一次。
- 静态属性会被提升
<div class="info"></div>
const hoisted = { class: 'info' }
render(cache) {
createVNode('div', hoisted, '')
}
预字符串化
当编译时遇到大量连续静态内容,会直接编译为一个普通字符串节点。
经过字符串化后就是字符串化后的元素。<ul class="info">
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
</ul>
缓存事件处理函数
<button @click="count++">add</button>
Vue2对事件的处理是动态生成的,而在Vue3中是放在_cache缓存中,该参数是一个数组,如果数组中没有该元素(即事件),则将该元素赋值一个事件;否则就直接使用缓存中的事件。// vue2
render(ctx) {
return createVNode("button", {
onClick: function($event) {
ctx.count++
}
})
}
// vue3
render(ctx, _cache) {
return createVNode("button", {
onClick: _cache[0] || (_cache[0] = $event => ctx.count++)
}
Block Tree
在Vue2中对比新旧两颗树时,不知道那些是静态/动态的。只能一层层比较,浪费了很长的事件用于“无意义”的比较。
而在Vue3中运用Block Tree
,它会标记动态节点(PatchFlag),在对比树时会过滤静态节点,将动态节点直接放在根节点,这样就节省了很大的对比时间。
PatchFlag
Vue2在节点之间对比的时候,并不知道节点中那些属性/信息会变化,所以会全部比较。
在Vue3中引入了PatchFlag,针对不同的Flag类型,Vue3会自动只比较相应的属性。
var PatchFlagNames = {
[1]: `TEXT`,
[2]: `CLASS`,
[4]: `STYLE`,
[8]: `PROPS`,
[16]: `FULL_PROPS`,
[32]: `HYDRATE_EVENTS`,
[64]: `STABLE_FRAGMENT`,
[128]: `KEYED_FRAGMENT`,
[256]: `UNKEYED_FRAGMENT`,
[512]: `NEED_PATCH`,
[1024]: `DYNAMIC_SLOTS`,
[2048]: `DEV_ROOT_FRAGMENT`,
[-1]: `HOISTED`,
[-2]: `BAIL`
};
下述代码就是Vue3中PatchFlag
在代码中的表现。1-代表了TEXT
类型是一个会变化的属性。
_createVNode("h1", null, _toDisplayString($props.msg), 1 /* TEXT */),