根据官方介绍
客户端渲染效率比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缓存中,该参数是一个数组,如果数组中没有该元素(即事件),则将该元素赋值一个事件;否则就直接使用缓存中的事件。// vue2render(ctx) {return createVNode("button", {onClick: function($event) {ctx.count++}})}// vue3render(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 */),
