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

青灯夜游
リリース: 2022-01-22 15:05:00
転載
3913 人が閲覧しました

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 までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!