Heim  >  Artikel  >  Web-Frontend  >  Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

青灯夜游
青灯夜游nach vorne
2022-01-22 15:05:003959Durchsuche

Warum kann ich den Index nicht als Schlüssel verwenden, wenn ich v-for in vue verwende? Der folgende Artikel wird Ihnen den Grund vorstellen, warum der Schlüsselwert von v-for nicht indexiert werden kann. Ich hoffe, er wird Ihnen hilfreich sein!

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

Warum kann der Schlüsselwert von v-for nicht der Index sein?

Wenn viele Leute über diese häufig gestellte Frage im Vorstellungsgespräch sprechen, fangen sie sofort an, über virtuelles DOM und Diff-Algorithmus zu sprechen. 虚拟DOMdiff算法 了。

讲这些没问题,但如果是我,一定先讲 v-for 的 key 值写成 index 会造成的问题,再讲原理。

曾经我写 v-for, key 值永远都是 index,直到有一天,我这么写造成了线上bug...

来看一下我的线上bug演示吧:

父组件代码
<Child
  v-for="(item, index) in list"
  :key="index"
  :count="item.count"
  :name="item.name"
  @delete="handleDelete(index)"
/>

list: [
    {
      count: 1,
      name: &#39;第1个元素&#39;
    },
    {
      count: 2,
      name: &#39;第2个元素&#39;
    },
    {
      count: 3,
      name: &#39;第3个元素&#39;
    }
  ]
  
handleDelete(index) {
  this.list.splice(index, 1)
},

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

如代码和gif演示,点击删除第2个元素,看上去似乎一切正常。

等一下,第三个元素的count值居然变成了2,wtf!!!

惊得我又去看了遍子组件的代码

子组件
<div>
  <span>{{ name }}</span>
  count值为:{{ innerCount }}
  <button @click="$emit(&#39;delete&#39;)">-</button>
</div>

props: {
  count: {
    type: Number,
    default: 0
  },
  name: {
    type: String,
    default: &#39;&#39;
  }
},
data() {
  return {
    innerCount: this.count
  } 
}

感觉也没什么不对的啊。

不信邪,我又多创建了点元素来删除,还试了下排序:

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

果然,不光删除元素有问题,排序也有问题。

把 key 值改成 item.name 再试一下。

<Child
  v-for="(item, index) in list"
  :key="item.name"
  :count="item.count"
  :name="item.name"
  @delete="handleDelete(index)"
/>

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

正常了。

这样看来,在 v-for 里把 key 值写成 index,非常危险啊。

在查阅了 vue 官方文档之后,我终于明白了原因:

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

不依赖子组件状态

子组件里有一行很关键的代码

data() {
  return {
    innerCount: this.count
  } 
}

子组件内部定义了 innerCount,这样子组件就有了自己的状态,按照官方文档的说明,这种情况下不能把 index 作为 key 值。

临时 DOM 状态

<div v-for="(item, index) in list1" :key="index">
  <input type="text" />
  <button @click="delClick(index)">删除</button>
</div>

Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?

删除了第2项,但是第3项在表单中的3变成了2,跟上面依赖子组件状态的例子是一样的。

总结

写列表渲染时, 依赖子组件状态或临时 DOM 状态的情况,如果有 删除、增加、排序这样的功能,不要把 index 作为 key。

事实上,写列表渲染时,永远不要把 index 做为 key,key 一定要是唯一标识。

至于原因,就要理解 diff

Es ist in Ordnung, darüber zu sprechen, aber wenn ich es wäre, würde ich zuerst über die Probleme sprechen, die durch das Schreiben des Schlüsselwerts von v-for als Index entstehen, und dann über das Prinzip sprechen.

Ich habe einmal v-for geschrieben und der Schlüsselwert war immer index, bis ich eines Tages dies schrieb und einen
    Online-Fehler
  • verursachte ...
  • Werfen wir einen Blick auf meine Online-Fehlerdemonstration:
  • rrreee

wie Code und GIF-Demonstration, klicken Sie, um das zweite Element zu löschen, alles scheint normal zu sein.

Moment mal, der Zählwert des dritten Elements ist tatsächlich 2 geworden, wtf! ! !

Ich war so schockiert, dass ich mir den Code der Unterkomponente noch einmal angeschaut haberrreee

Ich hatte das Gefühl, dass nichts falsch war. 🎜🎜Ich glaube nicht an das Böse, also habe ich weitere Elemente zum Löschen erstellt und auch versucht, sie zu sortieren: 🎜🎜Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?🎜🎜Natürlich gibt es nicht nur ein Problem beim Löschen von Elementen, sondern auch beim Sortieren. 🎜🎜Ändern Sie den Schlüsselwert in item.name und versuchen Sie es erneut. 🎜rrreee🎜Warum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?🎜🎜 Es ist normal. 🎜🎜Es scheint sehr gefährlich zu sein, den Schlüsselwert als Index in v-for zu schreiben. 🎜🎜Nachdem ich die offizielle Vue-Dokumentation konsultiert hatte, verstand ich endlich den Grund: 🎜
🎜Wenn Vue die mit v-for gerenderte Elementliste aktualisiert, verwendet es standardmäßig „In-Place-Update“. Strategie. Wenn die Reihenfolge der Datenelemente geändert wird, verschiebt Vue die DOM-Elemente nicht, um sie an die Reihenfolge der Datenelemente anzupassen, sondern aktualisiert jedes Element an seiner Stelle und stellt sicher, dass sie an jeder Indexposition korrekt gerendert werden. 🎜
🎜Dieser Standardmodus ist effizient, 🎜ist jedoch nur für Listenwiedergabeausgaben geeignet🎜, die nicht auf dem Unterkomponentenstatus oder dem temporären DOM-Status basieren (z. B. Formulareingabewerte). 🎜
🎜🎜Hängt nicht vom Zustand der Unterkomponente ab🎜🎜🎜Es gibt eine sehr kritische Codezeile in der Unterkomponente🎜rrreee🎜Der innerCount ist intern in der Unterkomponente definiert, sodass die Unterkomponente ihren eigenen Zustand hat Laut offizieller Dokumentation kann in diesem Fall der Index nicht als Schlüsselwert verwendet werden. 🎜🎜🎜Temporärer DOM-Status🎜🎜rrreee🎜4 .gif🎜🎜Das 2. Element wird gelöscht, aber das 3. Element im Formular wird zu 2, was dem obigen Beispiel für die Abhängigkeit vom Zustand einer Unterkomponente entspricht. 🎜

Zusammenfassung🎜🎜Beim Rendern einer Liste kommt es auf den Status der Unterkomponente oder den temporären DOM-Status an. Wenn Funktionen wie Löschen, Hinzufügen und Sortieren vorhanden sind, sollten Sie dies nicht tun Verwenden Sie den Index als Schlüssel. 🎜🎜Wenn Sie eine Liste zum Rendern schreiben, verwenden Sie niemals den Index als Schlüssel. Der Schlüssel muss eine eindeutige Kennung sein. 🎜🎜Um den Grund zu verstehen, müssen Sie den diff-Algorithmus verstehen. 🎜🎜Zu beantwortende Frage: 🎜🎜🎜Warum kann der Schlüssel nicht als Zufallszahl oder Zeitstempel geschrieben werden? 🎜🎜Warum muss der Schlüssel eine eindeutige Kennung sein? 🎜🎜🎜Keine Sorge, ich habe mir vorgenommen, 100 Artikel zu Vue-Problemen zu schreiben. Ich werde sie in den folgenden Artikeln langsam analysieren. 🎜🎜Ich hoffe, dass meine Vue-Artikelserie Ihnen auf dem Front-End-Weg hilfreich sein kann~🎜🎜[Verwandte Empfehlungen: 🎜vue.js Video-Tutorial🎜]🎜

Das obige ist der detaillierte Inhalt vonWarum kann der Schlüsselwert der v-for-Direktive in vue nicht index sein?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen