ホームページ >ウェブフロントエンド >Vue.js >v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

青灯夜游
青灯夜游転載
2022-01-22 15:05:004018ブラウズ

vue で v-for を使用するときにインデックスをキーとして使用できないのはなぜですか? v-for のキー値をインデックスにできない理由については、以下の記事で紹介していますので、ご参考になれば幸いです。

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

#v-for のキー値をインデックスにできないのはなぜですか?

このありふれた面接の質問について話すとき、多くの人はすぐに 仮想 DOMdiff アルゴリズム について話し始めます。

これらについて話すのは問題ありませんが、私だったら、まず v-for のキー値をインデックスとして記述することによって生じる問題について話してから、原理について話します。

私はかつて v-for を書いたことがありますが、キーの値は常にインデックスでした。ある日まで、これを書いて オンライン バグを引き起こしました...

私のオンライン バグ デモ:

父组件代码
<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)
},

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

コードと GIF のデモに示されているように、クリックして 2 番目の要素を削除すると、すべてが正常であるように見えます。

ちょっと待って、実際には 3 番目の要素のカウント値が 2 になりました。なんと! ! !

あまりにもショックだったので、サブコンポーネントのコードをもう一度見てみたら、

子组件
<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
  } 
}

何も問題がないように感じました。

信じられない場合は、削除する要素をさらに作成して並べ替えてみました。

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

案の定、削除に問題があっただけではありませんでした。要素だけでなく並べ替えも可能です。

キー値を item.name に変更して、再試行してください。

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

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

正常です。

v-forにインデックスとしてキー値を記述するのは非常に危険なようです。

vue の公式ドキュメントを参照した後、最終的にその理由がわかりました。

Vue が v-for を使用してレンダリングされた要素リストを更新しているとき、「インプレース更新」戦略がデフォルトで使用されます。データ項目の順序が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、各要素をその場で更新し、各インデックス位置で正しくレンダリングされるようにします。

このデフォルト モードは効率的ですが、 はサブコンポーネントの状態や一時的な DOM 状態 (フォーム入力値など) に依存しないリスト レンダリング出力にのみ適しています

サブコンポーネントの状態には依存しません

サブコンポーネントには非常に重要なコード行があります

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

innerCountはサブコンポーネントの内部で定義されているため、サブコンポーネントは独自の状態を持ちますが、公式ドキュメントによると、この場合、インデックスをキー値として使用することはできません。

一時的な DOM ステータス

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

v-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?

2 番目の項目は削除されましたが、フォーム内の 3 番目の項目は 2 に変更されました。サブコンポーネントの状態に依存する上記の例と同じです。

まとめ

リストレンダリングを記述する際、サブコンポーネントの状態や一時的なDOMの状態に応じて、削除、追加、ソートなどの機能がある場合は、インデックスをインデックスとして使用しないでください。キー。

実際、レンダリング用のリストを作成するときは、インデックスをキーとして使用しないでください。キーは一意の識別子である必要があります。

理由については、diff アルゴリズムを理解する必要があります。

回答すべき質問:

  • キーを乱数またはタイムスタンプとして書き込めないのはなぜですか?
  • なぜキーが一意の識別子である必要があるのですか?

vue の問題に関する記事を 100 件書くというフラグを立てたので、次の記事でゆっくり分析していきますので、ご安心ください。

私の vue シリーズの記事がフロントエンドの分野で役立つことを願っています~

[関連する推奨事項: vue.js ビデオ チュートリアル ]

以上がv-for ディレクティブのキー値を vue のインデックスにできないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。