key
vue官網(wǎng)推薦我們使用v-for時(shí),給每一個(gè)節(jié)點(diǎn)元素添加一個(gè)唯一的 key,其實(shí)不只是vue,react中在執(zhí)行列表渲染時(shí)也會(huì)要求給每個(gè)組件添加上key這個(gè)屬性。
要了解key的作用,首先我們要簡(jiǎn)單了解一下虛擬DOM的Diff算法
vue和react都實(shí)現(xiàn)了一套虛擬DOM,使我們可以不直接操作DOM元素,只操作數(shù)據(jù)便可以重新渲染頁(yè)面。而隱藏在背后的原理便是其高效的Diff算法。
vue和react的虛擬DOM的Diff算法大致相同,其核心是基于兩個(gè)簡(jiǎn)單的假設(shè):
1. 兩個(gè)相同的組件產(chǎn)生類似的DOM結(jié)構(gòu),不同的組件產(chǎn)生不同的DOM結(jié)構(gòu)。
2. 同一層級(jí)的一組節(jié)點(diǎn),他們可以通過(guò)唯一的id進(jìn)行區(qū)分。
基于以上這兩點(diǎn)假設(shè),使得虛擬DOM的Diff算法的復(fù)雜度從O(n^3)降到了O(n)。
好吧,這樣解釋,似乎有點(diǎn)籠統(tǒng)了,我們來(lái)看一個(gè)例子:
我們希望可以在B和C之間加一個(gè)F,

Diff算法默認(rèn)執(zhí)行起來(lái)是這樣的:

就是C更新成F,D更新成C,E更新成D,最后再插入E
所以我們需要使用key來(lái)給每個(gè)節(jié)點(diǎn)做一個(gè)唯一標(biāo)識(shí),Diff算法就可以正確的識(shí)別此節(jié)點(diǎn),找到正確的位置區(qū)插入新的節(jié)點(diǎn)。

所以一句話,key的作用主要是為了高效的更新虛擬DOM
寫(xiě)一個(gè)案例:
<div id="app">
<ul>
沒(méi)有加key
<li v-for="item in arr">
<input type="checkbox"/>{{item}}
</li>
<button @click="add">添加</button>
</ul>
<ul>
沒(méi)有加key
<li v-for="item in arr" :key="item">
<input type="checkbox"/>{{item}}
</li>
<button @click="add">添加</button>
</ul>
</div>
<script>
new Vue({
data(){
return{
arr:["a","b","c","d","e"]
}
},
methods:{
add(){
this.arr.splice(2,0,'f')
}
}
}).$mount("#app")
</script>
先選中C,當(dāng)沒(méi)有加key的插入F的時(shí)候,選中的狀態(tài)變化

可以看的出來(lái),算法是直接將C變成了F
那么我們?cè)賮?lái)看下,加了key的效果:

加了,算法可以準(zhǔn)確無(wú)誤的在b和c之間添加了一個(gè)f
數(shù)組方法
當(dāng)數(shù)據(jù)發(fā)生變化時(shí),Vue會(huì)自動(dòng)檢測(cè)數(shù)據(jù)的變化,視圖會(huì)發(fā)生對(duì)應(yīng)的更新。
Vue中包含了一組觀察數(shù)組編譯的方法,使用它們改變數(shù)組也會(huì)觸發(fā)視圖的更新
變異方法:會(huì)改變?cè)紨?shù)組

非變異方法:不會(huì)改變?cè)紨?shù)組,但是會(huì)返回一個(gè)新數(shù)組
- fliter()
- slice()
- concat()
<div id="app">
<ul>
<li v-for="item in arr" :key="item">{{item}}</li>
<button @click="add()">添加</button>
</ul>
</div>
<script>
new Vue({
data(){
return{
arr:["王者榮耀","絕地求生","c","d","e"]
}
},
methods:{
add(){
// push
// this.arr.push("全軍出擊", "aa0", "bb");
// pop
// this.arr.pop()
// shift 刪除數(shù)組中的第一個(gè)元素
// this.arr.shift()
//
// this.arr.unshift("123")
// this.arr.splice(1,2)
// this.arr.splice(1,0, "456","567")
// this.arr.splice(1,2, "456","567")
// 這樣修改數(shù)組中的元素,視圖是不會(huì)更新的
// this.arr[1] = "999"
// 使用vue的set方法更新
// 全局set
// Vue.set(this.arr, 1, "999")
// 當(dāng)前實(shí)例set
this.$set(this.arr, 1, "888")
}
}
}).$mount("#app")
</script>
直接修改數(shù)組中的元素,視圖是不會(huì)更新的,需要用到Vue中的set方法
// 這樣修改數(shù)組中的元素,視圖是不會(huì)更新的
// this.arr[1] = "999"
// 使用vue的set方法更新
// 全局set
// Vue.set(this.arr, 1, "999")
// 當(dāng)前實(shí)例set
this.$set(this.arr, 1, "888")