1、从vue2到vue3
网上一搜,比较官方的区别如下:
- vue2对TS支持不友好(所有属性都放在this对象上,用ts难以推断组件的数据类型)
- 大量的API挂载在Vue的原型上,难以实现TreeShaking。
- CompositionAPI 受ReactHook启发(均是函数不是类)
- vue2在架构层面对跨平台dom渲染开发支持不友好
- 对虚拟Dom进行了重写,对模板的编译进行了优化操作
在使用vue3之后可以明显感受到以下几点变化:
1、使用Composition API,更加方便。业务数据与业务逻辑可以整合写到一起。
2、不存在this使用,直接通过函数调用。
3、性能比vue2快。
4、更加友好的支持TS。
5、兼容Vue2。Composition API可以和Option API混合使用。
2、vue3性能优化原因
1、diff算法优化
在vue2中,虚拟dom是进行全量的对比。而vue3中使用静态标记实现懒比较。
编译时先生成dom树,vue3在含有变量的节点添加flag
标记,在比较时,只需要比较带有标记的元素节点。这样大大减少了对比量。 可以使用此网站查看vue3的编译部分源码。
示例
使用上文网站进行编译:
<div> <p>{{name}}</p> </div>
编译之后:
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, _toDisplayString(_ctx.name), 1 /* TEXT */) // 1 代表动态文本节点 PatchFlag附文末 ])) }
2、hoistStatic静态提升
vue2中无论元素是否参与更新,每次都会重新创建、然后再渲染。vue3中对于不参与更新的元素会做静态提升,只会被创建一次,在渲染时直接复用既可。
示例
使用上文网站进行编译:
<div> <p>111</p> <p>222</p> <p>233</p> <p>{{name}}</p> </div>
静态提升之前:
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, "111"), _createVNode("p", null, "222"), _createVNode("p", null, "233"), _createVNode("p", null, _toDisplayString(_ctx.name), 1 /* TEXT */) ])) }
静态提升之后:
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "111", -1 /* HOISTED */) const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "222", -1 /* HOISTED */) const _hoisted_3 = /*#__PURE__*/_createVNode("p", null, "233", -1 /* HOISTED */) export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _hoisted_1, _hoisted_2, _hoisted_3, _createVNode("p", null, _toDisplayString(_ctx.name), 1 /* TEXT */) ])) }
总结一句话:把不需要参与更新的元素放到外面定义,只需要创建一次。
3、cachHadlers 事件侦听器缓存
在默认情况下onClick会被视为动态绑定,每次都要去追踪事件变化。但是在vue3中,视为同一个函数,所以不会追踪其变化,直接缓存起来使用即可。
示例
使用上文网站进行编译:
<div> <button @click="btn"></button> </div> 复制代码
事件侦听之前(静态标记: 8):
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _ctx.btn }, null, 8 /* PROPS */, ["onClick"]) ])) } 复制代码
事件侦听之后:
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.btn && _ctx.btn(...args))) }) ])) } 复制代码
4、ssr渲染
- 当有大量静态的内容时候,这些呢容会被当做纯字符串推进一个buffer里面,即使存在动态的绑定,也会通过模板插值嵌进去。这样会比通过虚拟dom来渲染的快上很多
- 当静态内容大到一定量级的时候,会用_createStaticVNode方法在客户端去生成一个static node,这些静态node,会被直接innnerHTML,就不需要创建对象,然后根据对象渲染。
附PatchFlag标记:
TEXT = 1; // 1 动态文本节点 CLASS = 1 << 1, // 2 动态class STYLE = 1 << 2, // 4 动态style PROPS = 1 << 3, // 8 动态属性,但不包含类名和样式 FULL_PROPS = 1 << 4, // 16 具有动态key属性,当 key 需要改变时,需要进行完整的diff比较 HYDRATE_EVENTS = 1 << 5, // 32 带有监听事件的节点 STABLE_FRAGMENT = 1 << 6, // 64 一个不会改变子节点顺序的 fragment KEYED_FRAGMENT = 1 << 7, // 128 带有key属性的fragment 或 部分子节点有key UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有key的fragment NEED_PATCH = 1 << 9, // 512 一个节点只会进行非 props比较
作者:ClyingDeng
链接:https://juejin.cn/post/6926714564864114701
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。