Vue雙向繫結原理(一)文件片段DocumentFragment
DocumentFragment介紹
JavaScript有以下幾種建立節點的方式:
- createAttribute(name): 用指定名稱name建立特性節點
- createComment(text): 建立帶文字text的註釋節點
- createElement(tagname): 建立標籤名為tagname的節點
- createTextNode(text): 建立包含文字text的文字節點
- createDocumentFragment(): 建立文件碎片節點
前幾個比較簡單,我們也順便簡單說一下:
createAttribute(name)
用於建立一個指定名稱name的屬性,例如:
var att=document.createAttribute("class");
att.value="democlass";
//給h1標籤添加了一個`class="democlass"` 的屬性
document.getElementsByTagName("H1")[0].setAttributeNode(att);
createComment(text)
用於建立一個帶文字text的HTML註釋節點,例如:
var c=document.createComment("My personal comments");
document.body.appendChild(c);
//結果為 <!-- My personal comments -->
createElement(tagname)
用於建立一個指定名稱的HTML元素。這個是最常用的了。例如:
//建立一個<p></p>元素
var p=document.createElement("p");
createTextNode(text)
用於建立一個文字為text的文字節點,常跟createElement配合使用。例如:
var h=document.createElement("H1");
var t=document.createTextNode("Hello World");
h.appendChild(t);
上邊幾個方法用於建立節點,都非常簡單。當我們更新少量dom節點的時候,可以建立他們然後直接appendChild()插入DOM樹。但是如果我們要建立大量節點的時候,每次都建立再插入,會呼叫很多次appendChild()方法,會非常浪費效能。為了解決這個問題,就有了documentFragmeng文件片段,可以先把這些建立的元素放入文件片段,然後在把文件片段插入DOM樹,這樣就只會呼叫一次appendChild()方法了。
createDocumentFragment()
用於建立一個文件片段作為容器,其中可以包含多個dom節點。這裡有兩點需要特別注意的地方:
- 當把文件片段插入DOM樹的時候,只會把它的子節點插進去,它作為容器本身是不會進入DOM樹的。
- 當把DOM樹種的節點插入文件片段的時候,這些節點,會真的從DOM樹種消失。我們也把這個過程叫做劫持。
在Vue中的作用
上邊說清楚了documentFragment是幹嘛的,現在說說他在vue中的作用。
每個vue例項都有一個根元素id的屬性el,Vue物件通過它來找到要渲染的部分。之後使用createDocumentFragment()方法建立一個documentFragment,遍歷根元素的所有子元素,依次劫持並插入文件片段,將根元素掏空。然後執行Vue的編譯:遍歷documentFragment中的節點,對其中的v-for,v-text等屬性進行相應的處理。最後,把編譯完成後的documentFragment還給根元素。
這也就是為什麼,我們寫在模板中的HTML,有v-for,v-model
等屬性,而實際頁面F12之後卻沒有,因為那是Vue編譯之後返回的結果。