Vue3.0是如何變快的
阿新 • • 發佈:2021-12-22
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 }