vue-虛擬dom
虛擬dom
頻繁且複雜的dom操作通常是前端效能瓶頸的產生點,Vue提供了虛擬dom的解決辦法
虛擬的DOM的核心思想是:對複雜的文件DOM結構,提供一種方便的工具,進行最小化地DOM操作。這句話,也許過於抽象,卻基本概況了虛擬DOM的設計思想
(1) 提供一種方便的工具,使得開發效率得到保證
(2) 保證最小化的DOM操作,使得執行效率得到保證
也就是說,虛擬dom的框架/工具都是這麼做的:
- 根據虛擬dom樹最初渲染成真實dom
- 當資料變化,或者說是頁面需要重新渲染的時候,會重新生成一個新的完整的虛擬dom
- 拿新的虛擬dom來和舊的虛擬dom做對比(使用diff演算法)。得到需要更新的地方之後,更新內容
這樣的話,就能大量減少真實dom的操作,提高效能
什麼是虛擬dom?與key值的關係?
Virual DOM是用JS物件記錄一個dom節點的副本,當dom發生更改時候,先用虛擬dom進行diff,算出最小差異,然後再修改真實dom。
當用傳統的方式操作DOM的時候,瀏覽器會從構建DOM樹開始從頭到尾執行一遍流程,效率很低。而虛擬DOM是用javascript物件表示的,而操作javascript是很簡便高效的。虛擬DOM和真正的DOM有一層對映關係,很多需要操作DOM的地方都會去操作虛擬DOM,最後統一一次更新DOM。因而可以提高效能
虛擬DOM的Diff演算法
虛擬DOM中,在DOM的狀態發生變化時,虛擬DOM會進行Diff運算,來更新只需要被替換的DOM,而不是全部重繪。
在Diff演算法中,只平層的比較前後兩棵虛擬DOM樹的節點,沒有進行深度的遍歷。
1.如果節點型別改變,直接將舊節點解除安裝,替換為新節點,舊節點包括下面的子節點都將被解除安裝,如果新節點和舊節點僅僅是型別不同,但下面的所有子節點都一樣時,這樣做也是效率不高的一個地方。
2.節點型別不變,屬性或者屬性值改變,不會解除安裝節點,執行節點更新的操作。
3.文字改變,直接修改文字內容。
4.移動,增加,刪除子節點時:
如果想在中間插入節點F,簡單粗暴的做法是:解除安裝C,裝載F,解除安裝D,裝載C,解除安裝E,裝載D,裝載E。如下圖:
寫程式碼時,如果沒有給陣列或列舉型別定義一個key,就會採用上面的粗暴演算法。
如果為元素增加key後,Vue就能根據key,直接找到具體的位置進行操作,效率比較高。如下圖:
本尋著key值相同的即可複用的原則。
在v-for中提供key,一方面可以提高效能,一方面也會避免出錯
虛擬dom流程
<body>
<div id="content">
<p>2</p>
<ul class="list-group">
</ul>
</div>
<!-- <div id="myp">1</div> -->
<script src="./base/vue.js"></script>
<script>
//vue內部引入了虛擬dom概念 (js記憶體物件) 屬於記憶體資料,真實dom的一層對映
//1.vue在記憶體中生成一顆虛擬dom樹
var vDom = {
tag:"div",
attr:{
id:"content"
},
children:[
{tag:"p",content:"2"},
{tag:"ul",attr:{className:'list-group'}}
]
}
//2.將記憶體中的虛擬dom樹將其初始化渲染,渲染成一顆真實dom樹
//3.當我們修改vue例項中的data資料的時候
this.arr.push("<li>11111</li><li>22222</li>")
//4.將之前的虛擬dom樹結合更新的資料生成一顆新的虛擬dom
var newDom = {
tag:"div",
attr:{
id:"content"
},
children:[
{tag:"p",content:"2"},
{tag:"ul",attr:{className:'list-group'},children:[
{tag:"li",content:"11111"},
{tag:"li",content:"22222"}
]}
]
}
//5.將此次生成的新的虛擬dom與上一次的虛擬dom結構進行比對,對比差異(diff演算法)
//6.將對比的差異的部分進行重新的真實dom的渲染。
</script>
</body>