主题
vue3 的升级点
编译优化
diff 算法优化
Vue3
在diff
算法中相比Vue2
增加了静态标记
关于这个静态标记,其作用是为了会发生变化的地方添加一个flag
标记,下次发生变化的时候直接找该地方进行比较
静态提升
Vue3
中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用
这样就免去了重复的创建节点,大型应用会受益于这个改动,免去了重复的创建操作,优化了运行时候的内存占用
vue
<span>你好</span>
<div>{{ message }}</div>
js
// 没做提升
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (
_openBlock(),
_createBlock(
_Fragment,
null,
[
_createVNode("span", null, "你好"),
_createVNode("div", null, _toDisplayString(_ctx.message), 1 /* TEXT */),
],
64 /* STABLE_FRAGMENT */
)
);
}
js
// 做了提升
const _hoisted_1 = /*#__PURE__*/ _createVNode(
"span",
null,
"你好",
-1 /* HOISTED */
);
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (
_openBlock(),
_createBlock(
_Fragment,
null,
[
_hoisted_1,
_createVNode("div", null, _toDisplayString(_ctx.message), 1 /* TEXT */),
],
64 /* STABLE_FRAGMENT */
)
);
}
静态内容_hoisted_1
被放置在render
函数外,每次渲染的时候只要取 _hoisted_1
即可
同时 _hoisted_1
被打上了 PatchFlag
,静态标记值为 -1 ,特殊标志是负整数表示永远不会用于 Diff
事件监听缓存
js
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (
_openBlock(),
_createBlock("div", null, [
_createVNode(
"button",
{
onClick:
_cache[1] || (_cache[1] = (...args) => _ctx.onClick(...args)),
},
"点我"
),
])
);
}
上述发现开启了缓存后,没有了静态标记。也就是说下次diff
算法的时候直接使用
SSR 优化
当静态内容大到一定量级时候,会用createStaticVNode
方法在客户端去生成一个 static node,这些静态node
,会被直接innerHtml
,就不需要创建对象,然后根据对象渲染
Tree shanking
相比Vue2
,Vue3
整体体积变小了,除了移出一些不常用的 API,再重要的是Tree shanking
任何一个函数,如ref
、reavtived
、computed
等,仅仅在用到的时候才打包,没用到的模块都被摇掉,打包的整体体积变小
Tree shaking
是基于ES6
模板语法(import
与exports
),主要是借助ES6
模块的静态编译思想,在编译时就能确定模块的依赖关系,以及输入和输出的变量
响应式系统
vue2
中采用 defineProperty
来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter
和setter
,实现响应式
vue3
采用proxy
重写了响应式系统,因为proxy
可以对整个对象进行监听,所以不需要深度遍历
- 可以监听动态属性的添加
- 可以监听到数组的索引和数组
length
属性 - 可以监听删除属性
composition API
- 优化逻辑组织
- 优化逻辑复用