iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
Modern Web

< 從Vue開始,新的學習地圖 >系列 第 5

05 | 關於Vue 渲染函數

  • 分享至 

  • xImage
  •  

渲染函數

渲染機制

Virtual DOM

Vue的渲染機制是基於虛擬DOM

  • DOM 是由瀏覽器所產生的
  • VDOM(虛擬DOM)本身是一個JS的物件存在memory中

渲染時會遍歷VDOM並從中構建真實的DOM,這個過程為mount
VDOM的好處是可以經由程式創建、檢查、與組合,將DOM的操作留給渲染器
若有兩個VDOM則會遍歷這兩者並比較其中的差異,找出差異點並改到實際的DOM上,過程稱為patch


patch aka diffReconciliation

比較差異的算法,主要在找出需要更新的節點
判斷DOM與VDOM之間是否有改變,沒有就不再渲染到真實的DOM上,節約性能
info:https://juejin.cn/post/6844904078196097031
info:https://reactjs.org/docs/reconciliation.html


渲染的歷程

  1. Compiled: 模板第一次被編譯成渲染函式,return至VDOM中。此步驟也可以通過build完成
  2. Mount: 運行渲染器調用渲染函示,遍歷後會return至VDOM中,並基於VDOM創建一個真實的DOM。這步驟稱為響應式方式
  3. Patch: 如果有所變化會在重新運行一次,並且創立一個更新後的VDOM,並會在運行時遍歷新的VDOM並與舊的VDOM比較,若有改變在更新到實際的DOM上

模板與渲染函式

vue 的模板被編譯為VDOM, vue 也提供了API直接跳過模板並且編寫渲染函示

使用模板的優點:模板接近html使用方式,在使用上html、css更親民。 使用模板上更能提高VDOM的性能


編譯器與VDOM

React中的VDOM的缺點:當在比較兩者不同的VDOM時,為了確保正確,會直接拔除舊的VDOM,且從頭開始構建一個新的VDOM,造成memory的負擔

VUE使用的方式在於:同時在控制編譯器與運行,在編譯器可以跳過靜態分析模板與直接控制渲染函數的權利----混合的方式稱之為Compiler-Informed Virtual DOM


靜態hoisting

在模板中不會重建靜態的內容,所以會從vnode中被提升出來,並在每次的渲染時、與變化時都用同一個內容
若有足夠多的連續靜態元素,將會被壓縮成一個'靜態node'

<div>
  <div>foo</div> <!-- hoisted -->
  <div>bar</div> <!-- hoisted -->
  <div>{{ dynamic }}</div>
</div>

patch flag

在動態元素進行渲染時,Vue會在vnode創建中對於需要的更新類型進行編碼
並且對於不同類型給予patch flag,例如圖下右邊的參數2(class),單個元素中可以擁有多個flag,當運行渲染器時可以使用這些條件來確認是否要執行工作

同時vue對於vnode中的子節點模板定義flag,需要確定的是這些根節點是不變的,也同樣能被依照條件執行工作。


Tree flatting

所有return VDOM 的 root 是由 createElementBlock() 創建的

export function render() {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    /* children */
  ], 64 /* STABLE_FRAGMENT */))
}

言下之意就是,即是模板的是以一個區塊,因為不含任何的結構指令:
例如v-ifv-for,每一個區塊的後代都有一個patch flag為了穩定結構,以及其子節點也包含

結果被視為一個扁平的物件

div (block root)
- div with :id binding
- div with {{ bar }} binding

所以當組件需要重新被渲染時,只需要便遍歷 Tree flatting 而不是整個vnode,靜態的部分也被跳過,減少了VDOM遍歷vnode的數量


SSR 影響

patch flag \ Tree flatting 提升SSR的性能


小結

渲染機制:模板被編譯為渲染函示後,返回至VDOM中,再建立真實的DOM,這個過程稱為mount,若有變化時會遍歷舊的VDOM與新的VDOM之間的差別,再更新的DOM上,這個行為稱為patch。遍歷的過程中會先把靜態的vnode節點提升出來,只針對動態元素vnode編碼標記改變。例如v-if\v-for的被視為一個'區塊',同樣在更新的時候會被做標記,被視為一個扁平的物件,在更新時連同後代也會ㄧ同更新。


上一篇
04 | 開始建立吧!
系列文
< 從Vue開始,新的學習地圖 >5
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言