Vue的渲染機制是基於虛擬DOM
DOM 是由瀏覽器所產生的
VDOM(虛擬DOM)本身是一個JS的物件存在memory中
渲染時會遍歷VDOM並從中構建真實的DOM,這個過程為mount
VDOM的好處是可以經由程式創建、檢查、與組合,將DOM的操作留給渲染器
若有兩個VDOM則會遍歷這兩者並比較其中的差異,找出差異點並改到實際的DOM上,過程稱為patch
patch aka diff、Reconciliation
比較差異的算法,主要在找出需要更新的節點
判斷DOM與VDOM之間是否有改變,沒有就不再渲染到真實的DOM上,節約性能
info:https://juejin.cn/post/6844904078196097031
info:https://reactjs.org/docs/reconciliation.html
vue 的模板被編譯為VDOM, vue 也提供了API直接跳過模板並且編寫渲染函示
使用模板的優點:模板接近html使用方式,在使用上html、css更親民。 使用模板上更能提高VDOM的性能
React中的VDOM的缺點:當在比較兩者不同的VDOM時,為了確保正確,會直接拔除舊的VDOM,且從頭開始構建一個新的VDOM,造成memory的負擔
VUE使用的方式在於:同時在控制編譯器與運行,在編譯器可以跳過靜態分析模板與直接控制渲染函數的權利----混合的方式稱之為Compiler-Informed Virtual DOM
在模板中不會重建靜態的內容,所以會從vnode中被提升出來,並在每次的渲染時、與變化時都用同一個內容
若有足夠多的連續靜態元素,將會被壓縮成一個'靜態node'
<div>
<div>foo</div> <!-- hoisted -->
<div>bar</div> <!-- hoisted -->
<div>{{ dynamic }}</div>
</div>
在動態元素進行渲染時,Vue會在vnode創建中對於需要的更新類型進行編碼
並且對於不同類型給予patch flag,例如圖下右邊的參數2
(class),單個元素中可以擁有多個flag,當運行渲染器時可以使用這些條件來確認是否要執行工作
同時vue對於vnode中的子節點模板定義flag,需要確定的是這些根節點是不變的,也同樣能被依照條件執行工作。
所有return VDOM 的 root 是由
createElementBlock()
創建的
export function render() {
return (_openBlock(), _createElementBlock(_Fragment, null, [
/* children */
], 64 /* STABLE_FRAGMENT */))
}
言下之意就是,即是模板的是以一個區塊
,因為不含任何的結構指令:
例如v-if
、v-for
,每一個區塊的後代都有一個patch flag為了穩定結構,以及其子節點也包含
結果被視為一個扁平的物件
div (block root)
- div with :id binding
- div with {{ bar }} binding
所以當組件需要重新被渲染時,只需要便遍歷 Tree flatting 而不是整個vnode,靜態的部分也被跳過,減少了VDOM遍歷vnode的數量
patch flag \ Tree flatting 提升SSR的性能
渲染機制:模板被編譯為渲染函示後,返回至VDOM中,再建立真實的DOM,這個過程稱為mount,若有變化時會遍歷舊的VDOM與新的VDOM之間的差別,再更新的DOM上,這個行為稱為patch。遍歷的過程中會先把靜態的vnode節點提升出來,只針對動態元素vnode編碼標記改變。例如v-if\v-for的被視為一個'區塊',同樣在更新的時候會被做標記,被視為一個扁平的物件,在更新時連同後代也會ㄧ同更新。