1. diff 算法的优化
增加了静态标记, 被标记为-1的节点不会参与diff比较。
因为为vue3可以实现精准定位到动态节点,即那些可能需要重新渲染的节点。
曾经diff需要一层层比较整个新旧虚拟dom树找到哪些值改变。
- 现在vue3在编译时,利用静态标记patchFlag 标记节点的动态属性。
例如class、style、props,含有动态属性的节点就是动态节点。
2. 静态提升
对于静态节点,把创建dom节点的放在render函数之外。这样就只用创建一次,多次复用。
1 2 3 4 5 6
| export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock(_Fragment, null, [ _createVNode("span", null, "你好"), _createVNode("div", null, _toDisplayString(_ctx.message), 1 ) ], 64 )) }
|
提升后
1 2 3 4 5 6 7 8 9 10
| const _hoisted_1 = _createVNode("span", null, "你好", -1 )
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock(_Fragment, null, [ _hoisted_1, _createVNode("div", null, _toDisplayString(_ctx.message), 1 ) ], 64 )) }
|
3. 事件监听缓存
用一个cache缓存事件处理函数
1 2 3 4 5 6 7
| 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))) }, "点我") ])) }
|
4. Tree shaking
tree shaking 是一种清除多于代码的优化打包体积的技术。
- vue2中所有功能代码都被打包,因为vue2是单例模式,所有方法都在vue构造函数生成的单例上,treeshaking无法区分某个属性、方法是否用到。
- vue3利用ES6 module。 静态编译时就可以把未使用的功能排除
5. 响应式系统
- vue2 使用
defineProperty
来劫持对象,深度遍历所有属性给每个属性添加 getter setter
- vue3 使用
Proxy
代理对象。
defineProperty
只能劫持对象属性,所以需要遍历所有属性。而Proxy
是直接代理对象。
- vue2由于
defineProperty
而不能监听数组,所以要重写数组方法。
- 当一个对象的属性还是一个对象时,
Proxy
采用懒递归,在getter发现读到的属性时对象时才会创建该对象的代理并返回。