天天看點

Vue3.0學習——Vue3.0是如何變快的

  • Diff算法優化:

  1. Vue2.0 中的虛拟Dom是全量的對比
  2. Vue3.0 中新增了靜态标記(PatchFlag)

    在與上次的虛拟節點進行對比的時候,隻對比帶有patch flag的節點

    并且可以通過flag的資訊知道對比的内容

  • 靜态标記

    Vue3 中僅對靜态标記标記對象進行比較。
    <div>
      <p>wzl</p>
      <p>wzl</p>
      <p>wzl</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, "wzl"),
        _createVNode("p", null, "wzl"),
        _createVNode("p", null, "wzl"),
        _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
      ]))
    }
               
    可以看到,源碼中,對 msg 設計了靜态标記,這裡是1,後面跟注釋 TEXT ,代表這個标簽的 TEXT 資料是會動态變化的。
  • hoistStatic靜态提升

    1. Vue2中無論元素是否參與更新,每次都會重新建立然後渲染
    2. Vue3中對不參與的更新元素會做靜态提升,隻會被建立一次,在渲染時直接引用
/*
靜态提升之前
*/ 
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, "111"),
    _createVNode("p", null, "222"),
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */),
    _createVNode("p", null, "333")
  ]))
}
           
/*
靜态提升之後
不參與的更新元素會做靜态提升,隻會被建立一次,在渲染時直接引用
*/ 
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

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, "333", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _hoisted_1,
    _hoisted_2,
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */),
    _hoisted_3
  ]))
           
  • cacheHandelers事件偵聽器緩存

    預設情況下onClick會被視為動态綁定,是以每次都會追蹤它的變化

    但是是同一個函數,是以沒有變化,直接緩存起來複用即可

/*
開啟事件偵聽器緩存之前
*/ 
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", { onClick: _ctx.onClick }, 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.onClick(...args)))
    })
  ]))
}

           

_createVnode 的第二個屬性,從

{ onClick: _ctx.onClick }
           

變為了

{ onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))) }
           

它的意思很明顯,onClick 方法被存入 cache。在使用的時候,如果能在緩存中找到這個方法,那麼它将直接被使用。如果找不到,那麼将這個方法注入緩存。總之,就是把方法給緩存了。

例如:

<div>
  <button @click="onClick" @mouseover="onMouseover">btn</button>
  <button @click="onClick1">btn</button>
</div>
           
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", {
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))),
      onMouseover: _cache[2] || (_cache[2] = (...args) => (_ctx.onMouseover(...args)))
    }, "btn", 32 /* HYDRATE_EVENTS */),
    _createVNode("button", {
      onClick: _cache[3] || (_cache[3] = (...args) => (_ctx.onClick1(...args)))
    }, "btn")
  ]))
}
           

繼續閱讀