Vue中key的作用
創(chuàng)新互聯(lián)長(zhǎng)期為上1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為五峰企業(yè)提供專業(yè)的成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站,五峰網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。key
的特殊attribute
主要用在Vue
的虛擬DOM
算法,在新舊Nodes
對(duì)比時(shí)辨識(shí)VNodes
。如果不使用key
,Vue
會(huì)使用一種限度減少動(dòng)態(tài)元素并且盡可能的嘗試就地修改、復(fù)用相同類型元素的算法,而使用key
時(shí),它會(huì)基于key
的變化重新排列元素順序,并且會(huì)移除key
不存在的元素。此外有相同父元素的子元素必須有獨(dú)特的key
,重復(fù)的key
會(huì)造成渲染錯(cuò)誤。
相關(guān)學(xué)習(xí)推薦:javascript視頻教程
描述
首先是官方文檔的描述,當(dāng)Vue
正在更新使用v-for
渲染的元素列表時(shí),它默認(rèn)使用就地更新的策略,如果數(shù)據(jù)項(xiàng)的順序被改變,Vue
將不會(huì)移動(dòng)DOM
元素來(lái)匹配數(shù)據(jù)項(xiàng)的順序,而是就地更新每個(gè)元素,并且確保它們?cè)诿總€(gè)索引位置正確渲染。這個(gè)默認(rèn)的模式是高效的,但是只適用于不依賴子組件狀態(tài)或臨時(shí)DOM
狀態(tài)的列表渲染輸出,例如表單輸入值。為了給Vue
一個(gè)提示,以便它能跟蹤每個(gè)節(jié)點(diǎn)的身份,從而重用和重新排序現(xiàn)有元素,你需要為每項(xiàng)提供一個(gè)唯一key attribute
,建議盡可能在使用v-for
時(shí)提供key attribute
,除非遍歷輸出的DOM
內(nèi)容非常簡(jiǎn)單,或者是刻意依賴默認(rèn)行為以獲取性能上的提升。
簡(jiǎn)單來(lái)說(shuō),當(dāng)在列表循環(huán)中使用key
時(shí),需要使用key
來(lái)給每個(gè)節(jié)點(diǎn)做一個(gè)唯一標(biāo)識(shí),diff
算法就可以正確的識(shí)別此節(jié)點(diǎn),找到正確的位置直接操作節(jié)點(diǎn),盡可能地進(jìn)行重用元素,key
的作用主要是為了高效的更新虛擬DOM
。此外,使用index
作為key
是并不推薦的做法,其只能保證Vue
在數(shù)據(jù)變化時(shí)強(qiáng)制更新組件,以避免原地復(fù)用帶來(lái)的副作用,但不能保證限度的元素重用,且使用index
作為key
在數(shù)據(jù)更新方面和不使用key
的效果基本相同。
示例
首先定義一個(gè)Vue
實(shí)例,渲染四個(gè)列表,分別為簡(jiǎn)單列表與復(fù)雜列表,以及其分別攜帶key
與不攜帶key
時(shí)對(duì)比其更新渲染時(shí)的速度,本次測(cè)試使用的是Chrome 81.0
,每次在Console
執(zhí)行代碼時(shí)首先會(huì)進(jìn)行刷新重新加載界面,避免瀏覽器以及Vue
自身優(yōu)化帶來(lái)的影響。
<!DOCTYPE html> <html> <head> <title>Vue</title> </head> <body> <p id="app"> <ul> <li v-for="item in simpleListWithoutKey" >{{item}}</li> </ul> <ul> <li v-for="item in simpleListWithKey" :key="item" >{{item}}</li> </ul> <ul> <li v-for="item in complexListWithoutKey"> <span v-for="value in item.list" v-if="value > 5">{{value}}</span> </li> </ul> <ul> <li v-for="item in complexListWithKey" :key="item.id"> <span v-for="value in item.list" :key="value" v-if="value > 5">{{value}}</span> </li> </ul> </p> </body> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { simpleListWithoutKey: [1, 2, 3, 4, 5, 6], simpleListWithKey: [1, 2, 3, 4, 5, 6], complexListWithoutKey:[ {id: 1, list: [1, 2, 3]}, {id: 2, list: [4, 5, 6]}, {id: 3, list: [7, 8, 9]} ], complexListWithKey:[ {id: 1, list: [1, 2, 3]}, {id: 2, list: [4, 5, 6]}, {id: 3, list: [7, 8, 9]} ], } }) </script> </html>
簡(jiǎn)單列表
在簡(jiǎn)單列表的情況下,不使用key
可能會(huì)比使用key
的情況下在更新時(shí)的渲染速度更快,這也就是官方文檔中提到的,除非遍歷輸出的DOM
內(nèi)容非常簡(jiǎn)單,或者是刻意依賴默認(rèn)行為以獲取性能上的提升。在下面的例子中可以看到?jīng)]有key
的情況下列表更新時(shí)渲染速度會(huì)快,當(dāng)不存在key
的情況下,這個(gè)列表直接進(jìn)行原地復(fù)用,原有的節(jié)點(diǎn)的位置不變,原地復(fù)用元素,將內(nèi)容更新為5
、6
、7
、8
、9
、10
,并添加了11
與12
兩個(gè)節(jié)點(diǎn),而存在key
的情況下,原有的1
、2
、3
、4
節(jié)點(diǎn)被刪除,5
、6
節(jié)點(diǎn)保留,添加了7
、8
、9
、10
、11
、12
六個(gè)節(jié)點(diǎn),由于在DOM
的增刪操作上比較耗時(shí),所以表現(xiàn)為不帶key
的情況下速度更快一些。
// 沒(méi)有key的情況下 console.time(); vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 2.193056640625ms
// 存在key的情況下 console.time(); vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() => console.timeEnd()); // default: 3.2138671875ms
原地復(fù)用可能會(huì)帶來(lái)一些副作用,文檔中提到原地復(fù)用這個(gè)默認(rèn)的模式是高效的,但是只適用于不依賴子組件狀態(tài)或臨時(shí)DOM
狀態(tài)的列表渲染輸出,例如表單輸入值。
在不設(shè)置key
的情況下,元素中沒(méi)有與數(shù)據(jù)data
綁定的部分,Vue
會(huì)默認(rèn)使用已經(jīng)渲染的DOM
,而綁定了數(shù)據(jù)data
的部分會(huì)進(jìn)行跟隨數(shù)據(jù)渲染,假如操作了元素位置,則元素中未綁定data
的部分會(huì)停留在原地,而綁定了data
的部分會(huì)跟隨操作進(jìn)行移動(dòng),在下面的例子中首先需要將兩個(gè)A
之后的輸入框添加數(shù)據(jù)信息,這樣就制作了一個(gè)臨時(shí)狀態(tài),如果此時(shí)點(diǎn)擊下移按鈕,那么不使用key
的組中的輸入框?qū)⒉粫?huì)跟隨下移,且B
到了頂端并成為了紅色,而使用key
的組中會(huì)將輸入框進(jìn)行下移,且A
依舊是紅色跟隨下移。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>就地復(fù)用</title> </head> <body> <p id="app"> <h3>采用就地復(fù)用策略(vuejs默認(rèn)情況)</h3> <p v-for='(p, i) in persons'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> <h3>不采用就地復(fù)用策略(設(shè)置key)</h3> <p v-for='(p, i) in persons' :key='p.id'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> </p> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script> new Vue({ el: '#app', data: { persons: [ { id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 3, name: 'C' } ] }, mounted: function(){ // 此DOM操作將兩個(gè)A的顏色設(shè)置為紅色 主要是為了演示原地復(fù)用 document.querySelectorAll("h3 + p > span:first-child").forEach( v => v.style.color="red"); }, methods: { down: function(i) { if (i == this.persons.length - 1) return; var listClone = this.persons.slice(); var one = listClone[i]; listClone[i] = listClone[i + 1]; listClone[i + 1] = one; this.persons = listClone; } } }); </script> </body> </html> <!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->
復(fù)雜列表
使用key
不僅能夠避免上述的原地復(fù)用的副作用,且在一些操作上可能能夠提高渲染的效率,主要體現(xiàn)在重新排序的情況,包括在中間插入和刪除節(jié)點(diǎn)的操作,在下面的例子中沒(méi)有key
的情況下重新排序會(huì)原地復(fù)用元素,
但是由于v-if
綁定了data
所以會(huì)一并進(jìn)行操作,在這個(gè)DOM
操作上比較消耗時(shí)間,而使用key
得情況則直接復(fù)用元素,v-if
控制的元素在初次渲染就已經(jīng)決定,在本例中沒(méi)有對(duì)其進(jìn)行更新,所以不涉及v-if
的DOM
操作,所以在效率上會(huì)高一些。
console.time(); vm.complexListWithoutKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); vm.$nextTick(() => console.timeEnd()); // default: 4.100244140625ms
console.time(); vm.complexListWithKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); // default: 3.016064453125ms
分享名稱:代碼詳解Vue中key的作用示例
本文網(wǎng)址:http://muchs.cn/article0/cghgoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、域名注冊(cè)、網(wǎng)站內(nèi)鏈、企業(yè)網(wǎng)站制作、Google、動(dòng)態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)