1.diff算法优化

首先,diff算法是虚拟DOM技术的必然产物,它会对新旧虚拟DOM作对比(即diff),然后将变化的地方更新在真实DOM上。而这其中,如何快速的判别需要变化的内容,就是Vue3.0的提升。具体来看:

在Vue2.0当中,当数据发生变化,它就会新生成一个DOM树,并和之前的DOM树进行比较,找到不同的节点然后更新。但这比较的过程是全量的比较,也就是每个节点都会彼此比较。但其中很显然的是,有些节点中的内容是不会发生改变的,那我们对其进行比较就肯定消耗了时间。所以在Vue3.0当中,就对这部分内容进行了优化:在创建虚拟DOM树的时候,会根据DOM中的内容会不会发生变化,添加一个静态标记。那么之后在与上次虚拟节点进行对比的时候,就只会对比这些带有静态标记的节点。

为了方便看到结果,我们将代码转成Vue3源码就可看到效果:

对于这个静态标记为什么是数字1,PatchFlags目录中有详细叙述:

 

export const enum PatchFlags {
  // 动态文本节点
  TEXT = 1,

  // 动态 class
  CLASS = 1 << 1, // 2

  // 动态 style
  STYLE = 1 << 2, // 4

  // 动态属性,但不包含类名和样式
  // 如果是组件,则可以包含类名和样式
  PROPS = 1 << 3, // 8

  // 具有动态 key 属性,当 key 改变时,需要进行完整的 diff 比较。
  FULL_PROPS = 1 << 4, // 16

  // 带有监听事件的节点
  HYDRATE_EVENTS = 1 << 5, // 32

  // 一个不会改变子节点顺序的 fragment
  STABLE_FRAGMENT = 1 << 6, // 64

  // 带有 key 属性的 fragment 或部分子字节有 key
  KEYED_FRAGMENT = 1 << 7, // 128

  // 子节点没有 key 的 fragment
  UNKEYED_FRAGMENT = 1 << 8, // 256

  // 一个节点只会进行非 props 比较
  NEED_PATCH = 1 << 9, // 512

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

  // 静态节点
  HOISTED = -1,

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

  

2.静态提升 hoistStatic

在Vue中无论元素是否参与更新,每次都会重新创建,然后再渲染。如下图所示,每次都会createVNode。

 

 

 

但是在Vue3中使用了静态提升后,对于不参与更新的元素,只会被创建一次,在渲染时直接复用即可:

 

 

 

3.事件侦听器缓存 cacheHandlers

默认情况下onClick会被视为动态绑定,所以每次都会去追踪它的变化,但是因为是同一个函数,所以没必要去追踪它的变化,想办法将它直接缓存起来复用就会提升性能。

 

 

 

从上图就可以看到,onClick果然会被视为动态绑定,它有静态标记,查看刚才提到的目录中发现,8是动态属性。开启cacheHandlers后,静态标记就不存在了,那么这部分内容也就不会进行比较了。

 

posted on 2021-03-01 15:04  ygunoil  阅读(3782)  评论(0编辑  收藏  举报