Vue 中為何不可以使用Index 作為Dom的key?

GeekQiaQia發表於2019-04-07

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;

相關文章