Почему не всегда использовать индекс в качестве ключа в vue.js для цикла?

#javascript #vue.js #vuejs2

#javascript #индексирование #vue.js #Клавиша #v-для

Вопрос:

Я использовал vue.js для нескольких проектов и я использую индекс в качестве ключа в циклах for

 <div v-for="(item, index) in items" :key="index"></div>
 

… и начали задаваться вопросом, есть ли проблемы с этим, поскольку в примерах обычно используется идентификатор элемента.

 <div v-for="(item, index) in items" :key="item.ID"></div>
 

Ответ №1:

Потому что массивы изменчивы. Индекс любого заданного элемента может и будет меняться, если элементы добавляются в массив или удаляются из него.

Вы хотите, чтобы ваше key значение было уникальным значением, идентифицирующим только ваш уникальный компонент. Созданный вами первичный ключ всегда лучше, чем использование индекса.

Вот пример.

 console.clear()

Vue.component("item", {
  props: ["value"],
  data() {
    return {
      internalValue: this.value
    }
  },
  template: `<li>Internal: {{internalValue}} Prop: {{value}}</li>`
})


new Vue({
  el: "#app",
  data: {
    items: [1, 2, 3, 4, 5]
  },
  methods: {
    addValue() {
      this.items.splice(this.items.length / 2, 0, this.items.length   1)
    }
  }
}) 
 <script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  {{items}}
  <ul>
    <item v-for="i in items" :value="i" :key="i"></item>
  </ul>
  <button @click="addValue">AddValue</button>
  <ul>
    <item v-for="(i, index) in items" :value="i" :key="index"></item>
  </ul>
</div> 

Обратите внимание, что при addValue нажатии список сверху представляет новые числа в массиве, где они действительно находятся в массиве; в середине. Во втором списке под кнопкой значения не представляют фактическое местоположение в массиве, а внутренние значения и значения свойств не совпадают.

Комментарии:

1. @getsetbro Существуют способы устранения проблем, возникающих при использовании индекса в качестве ключа, и могут быть случаи, когда индекс — ваш единственный выбор, но идеальный случай — использовать правильный ключ.

2. Спасибо за пример. Что я узнал из этого, так это то, что свойство key позволяет Vue правильно отслеживать, где элемент находится в массиве, и отображать соответствующим образом. Однако я не понимаю, почему во втором списке internalValue будет отличаться от value , когда internalValue просто присваивается this.value . Есть ли где-нибудь, где я могу почитать дальше по этому вопросу?

3. @AlexAlexson data функция в компоненте выполняется только один раз за время существования компонента. Это присвоение является значением инициализации. При изменении value свойства в компоненте примера ничего не обновляется internalValue .

4. @Bert, AlexAlexson, следуйте встроенной стратегии исправления Vue для второго списка, поскольку нет правильного сопоставления индексов между состоянием приложения и DOM, новый элемент DOM будет добавлен в конец списка, и он инициализирует internalValue = value (теперь оно равно 5). Таким образом, вы увидите, что он всегда имеет значение 5 для internalValue в конце списка. Для получения дополнительной информации вы можете обратиться к: deepsource.io/blog/key-attribute-vue-js

5. Быстрая победа для уникального ключа: :key="something '-' '-' index '-' new Date().toString()"

Ответ №2:

 console.clear()

Vue.component("item", {
  props: ["value"],
  data() {
    return {
      internalValue: this.value
    }
  },
  template: `<li>Internal: {{internalValue}} Prop: {{value}}</li>`
})


new Vue({
  el: "#app",
  data: {
    items: [{name:'a'},{name:'b'},{name:'c'}]
  },
  methods: {
    addValue() {
      this.items = [{name:'a'},{name:6},{name:'b'},{name:'c'}];
    }
  }
}) 
 <script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  {{items}}
  <ul>
    <item v-for="i in items" :value="i.name" :key="i"></item>
  </ul>
  <button @click="addValue">AddValue</button>
  <ul>
    <item v-for="(i, index) in items" :value="i.name" :key="index"></item>
  </ul>
</div> 

Чтобы быть более ясным