Issue:'Vue 中為何不可以使用index作為key';
前提分析:在vue v-for 中,通常需要使用key,目的來提高更新DOM的效能問題;
隱患問題:如果引入key不當,會帶來狀態bug問題;
引用唐老師的程式碼示例:
1.定義子元件ListInput.vue; 在該元件中,data資料有phone;在template 模板中,input 標籤繫結資料phone;slot 插槽標籤作為佔位;
<template>
<div class="border2">
<input v-model="phone" type="number" />
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
phone: ""
};
}
};
</script>
複製程式碼
2.父元件phoneList.vue 中;
首先定義全域性變數key=1; 引用子元件ListInput,在template 模板標籤中,v-for:list-input子元件;並將index作為key值;
新增按鈕:繫結事件函式 handleAdd(); 處理邏輯為:每次講list[]中push進一個key++值;list-input 動態重新整理; 刪除按鈕:繫結事件函式 handleDelete(key);處理邏輯為:獲取當前key 值,並刪除改變原陣列,重新執行 v-for 重新整理;
<template>
<div class="border">
<list-input v-for="(key, index) in list" :key="index">
<button @click="() => handleDelete(key)">刪除</button>
</list-input>
<button @click="handleAdd">新增</button>
</div>
</template>
<script>
import ListInput from "./ListInput";
let key = 1;
export default {
components: {
Children
},
data() {
return {
list: []
};
},
methods: {
handleAdd() {
this.list.push(key++);
},
handleDelete(key) {
console.log(key);
// findIndex 遍歷value 值;如果為true,則返回index;
const index = this.list.findIndex(k => k === key);
console.log(index);
// arrayObject.splice(index,howmany,item); 返回被刪除的專案,直接改變原始陣列;
this.list.splice(index, 1);
console.log(this.list);
}
}
};
複製程式碼
如上程式碼,如果連續點選新增四次,list:[1,2,3,4]; 此時,如果點選key為2的刪除按鈕;則實際上在頁面中刪除的是key位4的input輸入框; 原因分析如下;
(3) [1, 3, 4, __ob__: Observer]
0: 1
1: 3
2: 4
length: 3
__ob__: Observer {value: Array(3), dep: Dep, vmCount: 0}
__proto__: Array
複製程式碼
此時再次執行v-for 迴圈,迴圈元件:key;由0 1 2 3 ;變為0 1 2 ;vue 將顯示:key為0 1 2 的元件;這也是動態key 帶來的bug;這不是我們想要期待的結果;
解決方案: 使用靜態key; 將以上phoneList.vue 改為如下: 使用靜態key值;作為dom 的key;
<template>
<div class="border">
<Children v-for="key in list" :key="key">
<button @click="() => handleDelete(key)">刪除</button>
</Children>
<button @click="handleAdd">新增</button>
</div>
</template>
<script>
import Children from "./Children";
let key = 1;
export default {
components: {
Children
},
data() {
return {
list: []
};
},
methods: {
handleAdd() {
this.list.push(key++);
},
handleDelete(key) {
const index = this.list.findIndex(k => k === key);
this.list.splice(index, 1);
}
}
};
</script>
複製程式碼
**總結:**如果使用原生元件div 或者 span ;因為它們內部沒有一個類似listInput中的phone 這樣的一個資料狀態,不會出現這樣的bug;因此最好的方式是使用靜態key;作為Dom的key;