在Vue在render每個template的時候,首先是先把template轉換成
Virtual DOM再去讓compiler轉譯成真正的DOM呈現在畫面上
而當我們對Vue Component的data做修改時,也是透過修改Virtual DOM
再透過diff來做找出最小化變化來修改DOM。
每個html在網頁上都可以轉化為DOM(Document Object Model)
一般來說,我們所看到的DOM如下
<div id="app"></div>
而我們可以把DOM轉乘對應的javascript Object如下:
var node = {
tagName: 'div',
attributes: [ { 'id': 'myId' } ],
children: []
};
假設我們要對這個node新增一個子結點,
首先,會在javascript物件先新增子結點,語法如下:
node.push({
tagName: 'div'
attributes: [ { 'id': 'childId' } ],
children: []
});
最後再更新到真正的DOM
update(originalNode, node);
然後看到的DOM就會如下:
<div id="myId">
<div id="childId"></div>
</div>
操作 DOM 的成本是昂貴的,現今網頁的 DOM Element 數量都頗大,瑣碎頻繁地更新容易成為效能瓶頸。
如果不直接操作 DOM,而是將頁面上的 DOM 經 parse/traversal 為 JavaScript 物件
暫存在某個地方,對這些物件操作,然後再更新到 DOM 上,這樣的成本相對較低。
備註:Virtual DOM 保證的並不是在所有狀況下
都比操作原本的 DOM 來得快速,
而是在普遍狀況下,不需經手動優化,仍能給予不錯的效能。
Vue.js 中的 Virtual DOM 就是所謂的 V-NODE ,
一般來說,我們常直接撰寫 HTML 或使用 來操作元件,
但如果我們想用改用 JavaScript 來操作元件?
這樣的方式就是操作 virtual DOM,我們可以在 render 來做這件事,
如下,建立一個新的 DOM element。
HTML部分:
<div id="app">
${ message }
<my-component level="1"></my-component>
</div>
javascript 的部分
Vue.component('my-component', {
render: function (createElement) {
return createElement(
'div', {},
[
createElement('p', 'Hello World 2!'),
]
)
}
});
var vm = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
message: 'Hello World!'
}
});
說明上圖過程:
對這個 object 進行模版語法解析,
轉為 AST node,最後生成一棵完整的 AST tree (抽象語法樹,abstract syntax tree)。
執行渲染函數會得到 v-node。
watcher 蒐集依賴、經由 observer 對 v-node 做資料綁定和更新。
v-node 經由 patch 後 render 為真正的 HTML。
例如:比對、重新綁定資料、更新必要的 DOM element。