1. 程式人生 > 其它 >Vue3.0是如何變快的

Vue3.0是如何變快的

1.diff演算法優化

+ Vue2中的虛擬dom是進行全量的對比 https://vue-next-template-explorer.netlify.app/
+ Vue3新增了靜態標記(PatchFlag),
  在與上次虛擬節點進行對比時候,只對比帶有patch flag的節點
  並且可以通過flag的資訊得知當前節點要對比的具體內容

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




<!-- 靜態提升之前 -->
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

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

2.hoistStatic 靜態提升

+ Vue2中無論元素是否參與更新, 每次都會重新建立, 然後再渲染
+ Vue3中對於不參與更新的元素, 會做靜態提升, 只會被建立一次, 在渲染時直接複用即可


<!-- 靜態提升之後 -->
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "mzs", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "mzs", -1 /* HOISTED */)
const _hoisted_3 = /*#__PURE__*/_createVNode("p", null, "mzs", -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.msg) + "}", 1 /* TEXT */)
  ]))
}

// Check the console for the AST

3.cacheHandlers 事件偵聽器快取

+ 預設情況下onClick會被視為動態繫結, 所以每次都會去追蹤它的變化
  但是因為是同一個函式,所以沒有追蹤變化, 直接快取起來複用即可

<!--開啟事件監聽快取之前-->
import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", { onClick: _ctx.onClick }, "按鈕", 8 /* PROPS */, ["onClick"])
  ]))
}

// Check the console for the AST



<!--開啟事件監聽快取之後-->
import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", {
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick && _ctx.onClick(...args)))
    }, "按鈕")
  ]))
}

// Check the console for the AST
注意點: 我們只需要觀察有沒有靜態標記即可 因為我們知道在Vue3的diff演算法中, 只有有靜態標記的才會進行比較, 才會進行追蹤

4.ssr渲染

+ 當有大量靜態的內容時候,這些內容會被當做純字串推進一個buffer裡面,
  即使存在動態的繫結,會通過模板插值嵌入進去。這樣會比通過虛擬dmo來渲染的快上很多很多。
+ 當靜態內容大到一定量級時候,會用_createStaticVNode方法在客戶端去生成一個static node,
  這些靜態node,會被直接innerHtml,就不需要建立物件,然後根據物件渲染。

附錄: 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, // 靜態節點
  // 指示在 diff 過程應該要退出優化模式
  BAIL = -2
}