首頁  >  文章  >  web前端  >  程式碼詳解Vue中key的作用範例

程式碼詳解Vue中key的作用範例

coldplay.xixi
coldplay.xixi轉載
2020-07-11 17:43:282385瀏覽

程式碼詳解Vue中key的作用範例

Vue中key的作用

key的特殊attribute主要用在Vue的虛擬DOM演算法,在新舊Nodes對比時辨識#VNodes 。如果不使用keyVue會使用一種最大限度減少動態元素並且盡可能的嘗試就地修改、重複使用相同類型元素的演算法,而使用key 時,它會基於key的變化重新排列元素順序,並且會移除key不存在的元素。另外有相同父元素的子元素必須有獨特的key,重複的key會造成渲染錯誤。

相關學習推薦:javascript影片教學

描述

首先是官方文件的描述,當Vue正在更新使用v-for渲染的元素清單時,它預設使用就地更新的策略,如果資料項目的順序被改變, Vue將不會移動DOM元素來符合資料項目的順序,而是就地更新每個元素,並確保它們在每個索引位置正確渲染。這個預設的模式是高效率的,但是只適用於不依賴子元件狀態或暫時DOM狀態的清單渲染輸出,例如表單輸入值。為了給Vue一個提示,以便它能追蹤每個節點的身份,從而重複使用和重新排序現有元素,你需要為每項提供一個唯一key attribute,建議盡可能在使用v-for時提供key attribute,除非遍歷輸出的DOM內容非常簡單,或是刻意依賴預設行為以取得效能上的提升。

簡單來說,當在清單循環中使用key時,需要使用key來為每個節點做一個唯一標識,diff演算法就可以正確的識別此節點,找到正確的位置直接操作節點,盡可能地進行重複使用元素,key的作用主要是為了高效的更新虛擬DOM。此外,使用index作為key是不建議的做法,其只能保證Vue在資料變更時強制更新元件,以避免原地重複使用帶來的副作用,但不能保證最大限度的元素重用,且使用index作為key在資料更新方面和不使用key的效果基本上相同。

範例

先定義一個Vue實例,渲染四個列表,分別為簡單列表與複雜列表,以及其分別攜帶key與不攜帶key時對比其更新渲染時的速度,本測試使用的是Chrome 81.0,每次在Console執行程式碼時首先會進行刷新重新載入介面,避免瀏覽器以及Vue自身優化帶來的影響。

<!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: &#39;#app&#39;,
 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>

簡單清單

在簡單清單的情況下,不使用key可能會比使用 key的情況下在更新時的渲染速度更快,這也就是官方文檔中提到的,除非遍歷輸出的DOM內容非常簡單,或者是刻意依賴默認行為以獲取性能上的提升。在下面的例子中可以看到沒有key的情況下列表更新時渲染速度會快,當不存在key的情況下,這個列表直接進行原地復用,原有的節點的位置不變,原地重複使用元素,將內容更新為5678# 、910,並加入了1112兩個節點,而有key的情況下,原有的1234節點被刪除,56節點保留,新增了789101112六個節點,由於在DOM的增刪運算上比較耗時,所以表現為不帶key的情況下速度更快一些。

// 没有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

原地重複使用可能會帶來一些副作用,文檔中提到原地復用這個預設的模式是高效的,但是只適用於不依賴子元件狀態或臨時DOM狀態的清單渲染輸出,例如表單輸入值。

在不设置key的情况下,元素中没有与数据data绑定的部分,Vue会默认使用已经渲染的DOM,而绑定了数据data的部分会进行跟随数据渲染,假如操作了元素位置,则元素中未绑定data的部分会停留在原地,而绑定了data的部分会跟随操作进行移动,在下面的例子中首先需要将两个A之后的输入框添加数据信息,这样就制作了一个临时状态,如果此时点击下移按钮,那么不使用key的组中的输入框将不会跟随下移,且B到了顶端并成为了红色,而使用key的组中会将输入框进行下移,且A依旧是红色跟随下移。

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width">
 <title>就地复用</title>
</head>
<body>

 <p id="app">
 <h3>采用就地复用策略(vuejs默认情况)</h3>
 <p v-for=&#39;(p, i) in persons&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p> 

 <h3>不采用就地复用策略(设置key)</h3>
 <p v-for=&#39;(p, i) in persons&#39; :key=&#39;p.id&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p>

 </p>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
 <script>
 new Vue({
 el: &#39;#app&#39;,
 data: {
 persons: [
 { id: 1, name: &#39;A&#39; },
 { id: 2, name: &#39;B&#39; },
 { id: 3, name: &#39;C&#39; }
 ]
 },
 mounted: function(){
 // 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用
 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 @霸都丶傲天 有修改-->

复杂列表

使用key不仅能够避免上述的原地复用的副作用,且在一些操作上可能能够提高渲染的效率,主要体现在重新排序的情况,包括在中间插入和删除节点的操作,在下面的例子中没有key的情况下重新排序会原地复用元素,

但是由于v-if绑定了data所以会一并进行操作,在这个DOM操作上比较消耗时间,而使用key得情况则直接复用元素,v-if控制的元素在初次渲染就已经决定,在本例中没有对其进行更新,所以不涉及v-ifDOM操作,所以在效率上会高一些。

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的作用範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:jb51.net。如有侵權,請聯絡admin@php.cn刪除