Vue 3.0 在編譯方面有哪些優化?


1. Vue.js 2.x 通過標記靜態節點,優化 diff 的過程

2. Vue.js 3.x 通過標記和提升所有的靜態根節點,diff 的時候只需要對比動態節點內容

  • Fragments ( 升級 Vetur 插件 )
  • 靜態提升
  • Patch flag
  • 緩沖事件處理函數

 

詳細解釋:

此處我們用到線上編譯器來查看 vue 2.x 與 vue3.x 的編譯區別~

 

1. 首先看一下,當文件內部,不包含任何內容時,Vue2.x 編譯是空的,Vue 3.x 編譯內部包含 render 函數,返回為null

 

 

2. 我們先放入一個 Dom, 可以看到 vue2.x 和 vue 3.x 編譯的部分完完全全重構了,之前 Vue2.x 采用,_c 的模式創建標簽,_v 為 Vnode 節點, 而當前的 Vue 3.x 通過 _createBlock 生成 block tree 

- Vue 2.x 數據更新並觸發重新渲染的粒度是組件級的,單個組件內部需要遍歷該組件的整個 vnode 樹

- Vue.js 3.0 做到了通過編譯階段對靜態模板的分析,編譯生成了 Block tree。Block tree 是一個將模版基於動態節點指令切割的嵌套區塊,每個區塊內部的節點結構是固定的。每個區塊只需要追蹤自身包含的動態節點。

 

 

3. 新引入Fragments(片段)特性:Vue 3.x 模板中不需要再創建一個唯一的根節點,模板里可以直接放文本內容或者很多同級的標簽, Vue2.x 需要唯一的節點

 

4.  靜態提升:靜態節點都會被提升到render 的外部,只有初始化時會被創建,再次調用render時不會再次創建,可以直接重用這些靜態節點對應的vnode

  

5. Patch flag 

首先看下面這個案例,模版中有三個div標簽,其中只有最后一個標div簽的TEXT部分是動態的

 

 在之前的VDOM中,如果msg值發生改變,整個模版中的所有元素都需要重新渲染。但在Vue3.0中,在這個模版編譯時,編譯器會在動態標簽末尾加上 /* Text*/ PatchFlag。只能帶patchFlag 的 Node 才被認為是動態的元素,會被追蹤屬性的修改。並且 PatchFlag 會標識動態的屬性類型有哪些,比如這里 的TEXT 表示只有節點中的文字是動態的。

 

6. cacheHandler 緩存事件處理函數減少了不必要的更新操作

正常情況下,當綁定一個事件:

<div>
  <p @click="handleClick">靜態代碼</p>
</div>

模版會被編譯為

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", { onClick: _ctx.handleClick }, "靜態代碼", 8 /* PROPS */, ["onClick"])
  ]))
}

其中事件會每次從全局上下文中獲取。而當開啟了cacheHandler之后 

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("p", {
      onClick: _cache[1] || (_cache[1] = ($event, ...args) => (_ctx.handleClick($event, ...args)))
    }, "靜態代碼")
  ]))
}

編輯器會為你動態創建一個內聯函數,內聯函數里面再去飲用當前組件上最新的handler。之后編輯器會將內聯函數緩存。每次重新渲染時如果事件處理器沒有變,就會使用緩存中的事件處理而不會重新獲取事件處理器。這個節點就可以被看作是一個靜態的節點。這種優化更大的作用在於當其作用域組件時,之前每次重新渲染都會導致組件的重新渲染,在通過handler緩存之后,不會導致組件的重新渲染了。  

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM