10

vue3初探-vue3.0 是如何变快的

 3 years ago
source link: https://aoppp.com/vue3chu-tan-vue3wei-shi-yao-hui-bi-vue2kuai/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在开始介绍之前,先给大家推荐一个网站https://vue-next-template-explorer.netlify.app。这是Vue3官方演示Vdom的示例网站,本篇文章也是基于它进行演示的。

Vue3 在 Vdom 的更新时,只会关注它有变化的部分。这样的优化使 Vue3 既跳出了 Vdom 的性能瓶颈,又依然保留了可以手写 render function 的灵活性。相当于 Vue3 既有 react 的灵活性,又有基于模板的性能保证。——尤雨溪

diff算法优化

我们现在来看看同样的html,在vue2和vue3的渲染中对比出不同之处

<div>
    <p>空空</p>
    <p>{{msg}}</p>
 </div>

vue2的本质是在对比两个树(对象)

1606209762-1-.jpg

vue3会在创建虚拟DOM的时候,会根据DOM的内容会不会发生变化,添加一个静态标记

1606210402-1-.jpg

看完图,我们来看看vue3的render函数,会发现有变量的节点创建时会给到静态标记 (PatchFlags)去标识

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    // DOM的内容不会变化的元素
    _createVNode("p", null, "空空"),
    // DOM的内容会变化的元素
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

从上述两张图的对比中,以及代码中,我们可以得出

1.vue2中的虚拟DOM是进行全量的对比
2.vue3新增了静态标记(PatchFlags),只对比带有patch flag的节点的虚拟DOM,并且可以通过flag的信息得知当前节点要对比的具体内容

复用优化(静态提升)

静态提升(hoisStatic)

  • 静态提升
    • vue2中无论元素是否参与更新,每次都需要重新创建
    • vue3对于不参与更新的元素,只会被创建一次,之后每次渲染时会不断复用
  • 静态提升之前
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 */)
  ]))
}
  • 静态提升之后
// 把不需要更新的元素,提升出来
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 */)
  ]))
}

最后附上静态标记取值(PatchFlags)

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 过程应该要退出优化模式
}

本文为作者原创或转载,允许转载,由憧憬在 aoppp.com发布 转载请说明文章出处。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK