vue3.0为什么性能会比2.x快

2021-03-29  本文已影响0人  唐吉柯德

文章开始之前我先备注下本篇文章需要使用到的工具网站,他们的作用是把模板生成render函数
Vue Template Explorer
vue2:https://vue-template-explorer.netlify.app/
vue3:https://vue-next-template-explorer.netlify.app/

1)静态标记(patchFlag)

Vue2中的虚拟dom是进行全量对比的
Vue3新增了静态标记(PatchFlag),在与上次数据虚拟节点对比的时候只对比有patchFlag的节点,并且可以通过静态标记得到本次要对比的内容

patchFlag(静态标签).png

可以在Vue3 Template Explorer中得到验证

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", null, "这是一个段落"),
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

很明显我们可以看见生成的render函数中有一个标记1,至于1代码什么意思我们可以查看VUE3的源码
目录为:vue-next-master/packages/shared/src/patchFlags.ts


export const enum PatchFlags {

  TEXT = 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比较

  DYNAMIC_SLOTS = 1 << 10,//1024 动态slot

  HOISTED = -1,//静态节点

  BAIL = -2//指示在diff过程应该要退出优化模式

}

2)静态提升(hoistStatic)

vue2中无论元素是否参与更新,都会被重新创建
vue3中不需要参与更新的dom只会被创建一次并缓存,之后每一次都使用缓存即可

<!--测试模板-->
<div>
  <p>这是一个段落</p>
  <p>{{msg}}</p>
</div>

可以根据vue通过模板生成render函数的网站来进行测试

//vue3 Template Explorer默认不勾选右上角options的hoistStatic时
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", null, "这是一个段落"),
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}
//vue3 Template Explorer勾选右上角options的hoistStatic时
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "这是一个段落", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _hoisted_1,
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

很明显,勾选右上角options的hoistStatic之后,将不用更新的dom缓存成了一个全局变量hoisted,之后render函数的每一次执行都不会再创建这个dom

3)事件侦听缓存(cacheHandles)

默认情况下时间侦听被视为动态绑定,所以每次都会追踪他的变化,但是因为为同一函数,所以没有必要追踪变化,直接缓存起来复用即可

同样的我们还是在vue3 Template Explorer中来测试一下

<!--测试模板-->
<div>
    <p @click="onClick"></p>
</div>
//vue3 Template Explorer默认不勾选cacheHandlers时生成的render函数
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", { onClick: _ctx.onClick }, null, 8 /* PROPS */, ["onClick"])
  ]))
}
//vue3 Template Explorer勾选cacheHandlers之后生成的render函数
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", {
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick && _ctx.onClick(...args)))
    })
  ]))
}

结果依然明显,勾选cacheHandlers之后,创建的p节点上面少了一个8的标记

4)服务端渲染的优化

1,当有大量静态内容的时候,这些内容会被当做纯字符串推进一个buffer里面,即使存在动态的绑定,会通过模板插值嵌入进去,这样会比虚拟DOM来渲染快上很多很多
2,当静态内容大到一定量级的时候,会通过_createStaticVNode方法在客户端生成一个static node,这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。
那么这一章我们主要以Vue Template Explorer生成render函数的方式来讲了下一vue3的三个新特性patchFlag,hoistStatic,cacheHandles即静态标记,静态提升,事件侦听缓存,以及描述了下服务端渲染的优化

上一篇 下一篇

猜你喜欢

热点阅读