ホームページ >ウェブフロントエンド >Vue.js >vue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?

vue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?

青灯夜游
青灯夜游転載
2022-05-19 21:09:454254ブラウズ

vue のキーとは何ですか?次の記事では、vue のキーの原理と、キーを設定する場合と設定しない場合の違いについて説明します。

vue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?

#1. キーとは何ですか

始める前に、2 つの実際の作業シナリオを復元しましょう

  • #v-for

    を使用する場合は、ユニット # に key

    <ul>
        <li v-for="item in items" :key="item.id">...</li>
    </ul>
## を追加する必要があります。
    new Date()
  • によって生成されたタイムスタンプを

    key として使用し、手動で再レンダリングを強制します

    <Comp :key="+new Date()" />

    では、その背後にあるロジックは何ですかこれ?、
  • key
の機能は何ですか?

一言で言えば、

key は各 vnode に与えられる一意の ID であり、diff の最適化戦略でもあります。それに基づいて、対応するものをより正確かつ高速に見つけることができます。 vnode ノード。

(学習ビデオ共有:

vue ビデオ チュートリアル ) 舞台裏のロジック

使用する場合 v- When

には、

key を追加する必要があります。キーが使用されていない場合、Vue はインプレース復元の原則を採用します。つまり、要素の移動を最小限に抑え、ある程度、同じタイプの要素を同じ適切な場所にパッチまたは再利用します。

    キーが使用されている場合、Vue はキーの順序に従って要素を記録します。かつてキーを所有していた要素が表示されなくなった場合、その要素は直接削除または破棄されます
  • Use
  • new Date()
生成されたタイムスタンプは

key として使用され、再レンダリングを手動で強制的にトリガーします新しい値での再レンダリングがをキーとして使用すると、新しいキー Comp が表示され、古いキー Comp が削除され、新しいキー Comp がレンダリングをトリガーします

  • 2。キーの設定との違いキーを設定しない

例 例: インスタンスを作成し、2 秒後に

items

配列にデータを挿入します。 ## を使用せずに

<body>
  <div id="demo">
    <p v-for="item in items" :key="item">{{item}}</p>
  </div>
  <script src="../../dist/vue.js"></script>
  <script>
    // 创建实例
    const app = new Vue({
      el: &#39;#demo&#39;,
      data: { items: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;] },
      mounted () {
        setTimeout(() => { 
          this.items.splice(2, 0, &#39;f&#39;)  // 
       }, 2000);
     },
   });
  </script>
</body>
#key,

vue

この操作が実行されます:

プロセス全体を分析します:

vue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?

Compare A 、A、同じタイプのノードを比較し、

パッチ

を実行しますが、データが同じであるため、操作は実行されません
    dom
  • B、B、ノードを比較します同じタイプのノードを比較するため、patch を実行しますが、データが同じであるため、発生しません
  • dom
  • 操作同じタイプの C、F、ノードを比較し、実行しますpatch、データが異なります、
  • dom
  • 操作が発生します 同じタイプの D、C、ノードを比較し、patch、データを実行しますは異なります、
  • dom
  • 操作が発生します 同じタイプの E、D、ノードを比較し、patch を実行します、データは異なります、
  • dom
  • 操作が発生します ループが終了し、DOM
  • に E を挿入します。合計 3 回の更新と 1 回の挿入操作が発生します。
  • ## を使用する場合#key
:

vue

は次の操作を実行します:

A、A、同じタイプのノードを比較し、patch を実行しますが、データは同じですが、

dom
    操作は発生しません
  • 同じタイプの B、B、ノードを比較し、patch を実行しますが、データは同じですが dom
  • 操作が発生します
  • 異なるタイプの C、F ノードを比較します 同じタイプのノード E、E を比較し、patch
  • を実行しますが、データが同じであるため、
  • dom
      操作は発生しません
    • D、D、同じタイプのノードを比較し、実行patch
    • しますが、データは同じです、
    dom
  • 操作は発生しません
  • 同じタイプのノードである C と C を比較し、patch を実行しますが、データは同じです、いいえ dom
  • 操作が発生します
  • ##F が C に挿入される前にループが終了します##合計 0 回の更新と 1 回の挿入操作が発生しました#上の 2 つの小さな例を見ると、key
  • を設定すると、ページ上の
  • DOM
  • 操作が大幅に削減され、
diff

の効率が向上することがわかります。

キー値を設定すると差分効率が確実に向上しますか?

実際には、そうではありません。このドキュメントには、Vue.js が v-for を使用してレンダリングされた要素リストを更新する場合、デフォルトは "in" であることも明記されています。 「場所の再利用」戦略。データ項目の順序が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、単に各要素をここで再利用し、特定のインデックスでレンダリングされた各要素が表示されるようにします。 このデフォルト モードは効率的ですが、サブコンポーネントの状態や一時的な DOM 状態 (フォーム入力値など) に依存しないリスト レンダリング出力にのみ適しています。

これを使用することをお勧めします。可能な限り v-for の場合は

key

を指定してください。ただし、出力 DOM コンテンツの走査が非常に簡単である場合、またはパフォーマンスを向上させるためにデフォルトの動作に意図的に依存している場合は除きます。

三、原理分析

源码位置:core/vdom/patch.js 

里判断是否为同一个key,首先判断的是key值是否相等如果没有设置key,那么keyundefined,这时候undefined是恒等于undefined

function sameVnode (a, b) {
    return (
        a.key === b.key && (
            (
                a.tag === b.tag &&
                a.isComment === b.isComment &&
                isDef(a.data) === isDef(b.data) &&
                sameInputType(a, b)
            ) || (
                isTrue(a.isAsyncPlaceholder) &&
                a.asyncFactory === b.asyncFactory &&
                isUndef(b.asyncFactory.error)
            )
        )
    )
}

updateChildren方法中会对新旧vnode进行diff,然后将比对出的结果用来更新真实的DOM

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
    ...
    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
        if (isUndef(oldStartVnode)) {
            ...
        } else if (isUndef(oldEndVnode)) {
            ...
        } else if (sameVnode(oldStartVnode, newStartVnode)) {
            ...
        } else if (sameVnode(oldEndVnode, newEndVnode)) {
            ...
        } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
            ...
        } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
            ...
        } else {
            if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
            idxInOld = isDef(newStartVnode.key)
                ? oldKeyToIdx[newStartVnode.key]
                : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
            if (isUndef(idxInOld)) { // New element
                createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
            } else {
                vnodeToMove = oldCh[idxInOld]
                if (sameVnode(vnodeToMove, newStartVnode)) {
                    patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
                    oldCh[idxInOld] = undefined
                    canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
                } else {
                    // same key but different element. treat as new element
                    createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
                }
            }
            newStartVnode = newCh[++newStartIdx]
        }
    }
    ...
}

(学习视频分享:web前端开发编程基础视频

以上がvue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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