vue のキーとは何ですか?次の記事では、vue のキーの原理と、キーを設定する場合と設定しない場合の違いについて説明します。
を使用する場合は、ユニット # に key
<ul> <li v-for="item in items" :key="item.id">...</li> </ul>
key として使用し、手動で再レンダリングを強制します
<Comp :key="+new Date()" />
一言で言えば、
key は各 vnode に与えられる一意の ID であり、diff の最適化戦略でもあります。それに基づいて、対応するものをより正確かつ高速に見つけることができます。 vnode ノード。
(学習ビデオ共有:key を追加する必要があります。キーが使用されていない場合、Vue はインプレース復元の原則を採用します。つまり、要素の移動を最小限に抑え、ある程度、同じタイプの要素を同じ適切な場所にパッチまたは再利用します。
key として使用され、再レンダリングを手動で強制的にトリガーします
新しい値での再レンダリングがをキーとして使用すると、新しいキー Comp が表示され、古いキー Comp が削除され、新しいキー Comp がレンダリングをトリガーします
配列にデータを挿入します。 ## を使用せずに
<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: '#demo', data: { items: ['a', 'b', 'c', 'd', 'e'] }, mounted () { setTimeout(() => { this.items.splice(2, 0, 'f') // }, 2000); }, }); </script> </body>
#key
, vue この操作が実行されます:
パッチ
を実行しますが、データが同じであるため、操作は実行されません
B、B、ノードを比較します同じタイプのノードを比較するため、patch
を実行しますが、データが同じであるため、発生しません
同じタイプの C、F、ノードを比較し、実行しますpatch
、データが異なります、
同じタイプの D、C、ノードを比較し、patch
、データを実行しますは異なります、
同じタイプの E、D、ノードを比較し、patch
を実行します、データは異なります、
ループが終了し、DOM
に E を挿入します。合計 3 回の更新と 1 回の挿入操作が発生します。
vue
は次の操作を実行します:A、A、同じタイプのノードを比較し、
patch
を実行しますが、データは同じですが、
同じタイプの B、B、ノードを比較し、
patch を実行しますが、データは同じですが
dom異なるタイプの C、F ノードを比較します
同じタイプのノード E、E を比較し、
patch
D、D、同じタイプのノードを比較し、実行
patch同じタイプのノードである C と C を比較し、
patch を実行しますが、データは同じです、いいえ
dom
##合計 0 回の更新と 1 回の挿入操作が発生しました#上の 2 つの小さな例を見ると、
keyの効率が向上することがわかります。
キー値を設定すると差分効率が確実に向上しますか?実際には、そうではありません。このドキュメントには、
Vue.js が v-for を使用してレンダリングされた要素リストを更新する場合、デフォルトは "in" であることも明記されています。 「場所の再利用」戦略。データ項目の順序が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、単に各要素をここで再利用し、特定のインデックスでレンダリングされた各要素が表示されるようにします。
このデフォルト モードは効率的ですが、サブコンポーネントの状態や一時的な DOM 状態 (フォーム入力値など) に依存しないリスト レンダリング出力にのみ適しています。
を指定してください。ただし、出力 DOM コンテンツの走査が非常に簡単である場合、またはパフォーマンスを向上させるためにデフォルトの動作に意図的に依存している場合は除きます。
源码位置:core/vdom/patch.js
里判断是否为同一个key
,首先判断的是key
值是否相等如果没有设置key
,那么key
为undefined
,这时候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] } } ... }
以上がvue のキーとは何ですか?キーを設定する場合と設定しない場合の違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。