#Vue におけるキーの役割
key の特別な
attribute は、主に
Vue の仮想
DOM アルゴリズムで、古いものと新しい ## を比較するときに
VNode を識別するために使用されます。 #ノード
。 key
が使用されない場合、Vue
は動的要素を最小限に抑えるアルゴリズムを使用し、可能な限り同じタイプの要素を適切な場所で変更して再利用しようとします。代わりに ## を使用してください。 #key では、
key の変更に基づいて要素の順序が並べ替えられ、
key が存在しない要素が削除されます。さらに、同じ親要素を持つ子要素には一意の
key が必要です。
key を繰り返すとレンダリング エラーが発生します。
関連する学習の推奨事項:
説明
##最初は公式ドキュメントの説明です。Vue が
v-for を使用してレンダリングされた要素リストを更新するとき、デフォルトでインプレース更新戦略が使用されます。データ項目が変更された場合、Vue
はデータ項目の順序に一致するように DOM
要素を移動しませんが、各要素をその場で更新し、各インデックス位置で正しくレンダリングされるようにします。このデフォルト モードは効率的ですが、子コンポーネントの状態や一時的な DOM
状態 (フォーム入力値など) に依存しないリスト レンダリング出力にのみ適しています。 Vue
にヒントを与えて各ノードの ID を追跡し、既存の要素を再利用したり並べ替えたりできるようにするには、項目ごとに一意の key 属性
を提供する必要があります。出力 DOM
のコンテンツの走査が非常に単純であるか、意図的にデフォルトの動作に依存している場合を除き、v-for
を使用する場合は key 属性
を提供する可能性があります。パフォーマンスの向上のため。 簡単に言うと、リスト ループで
key
を使用する場合、
を使用して各ノードを一意に識別する必要があります。diff
アルゴリズムは次のことを行うことができます。このノードを正しく識別し、ノードを直接操作するための正しい位置を見つけ、要素を可能な限り再利用します。key
の役割は主に、仮想 DOM
を効率的に更新することです。また、index
を key
として使用することは推奨されません。データ変更時に Vue
が強制的にコンポーネントを更新することを保証できるのは、その場での更新を避けるためだけです。これは副作用をもたらしますが、要素の最大限の再利用を保証することはできず、index
を key
として使用すると、基本的に key
を使用しない場合と同じデータ更新効果があります。 。 例
最初に Vue インスタンスを定義し、単純なリストと複雑なリストという 4 つのリストをレンダリングします。
key を保持する場合と key
を保持しない場合の更新とレンダリングの速度。このテストは、毎回 Console
で実行するときに、Chrome 81.0
を使用します。コードを実行すると、ブラウザと Vue
自体の最適化の影響を回避するために、インターフェイスが最初に更新および再ロードされます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;"><!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<p id="app">
<ul>
<li v-for="item in simpleListWithoutKey" >{{item}}</li>
</ul>
<ul>
<li v-for="item in simpleListWithKey" :key="item" >{{item}}</li>
</ul>
<ul>
<li v-for="item in complexListWithoutKey">
<span v-for="value in item.list" v-if="value > 5">{{value}}</span>
</li>
</ul>
<ul>
<li v-for="item in complexListWithKey" :key="item.id">
<span v-for="value in item.list" :key="value" v-if="value > 5">{{value}}</span>
</li>
</ul>
</p>
</body>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: &#39;#app&#39;,
data: {
simpleListWithoutKey: [1, 2, 3, 4, 5, 6],
simpleListWithKey: [1, 2, 3, 4, 5, 6],
complexListWithoutKey:[
{id: 1, list: [1, 2, 3]},
{id: 2, list: [4, 5, 6]},
{id: 3, list: [7, 8, 9]}
],
complexListWithKey:[
{id: 1, list: [1, 2, 3]},
{id: 2, list: [4, 5, 6]},
{id: 3, list: [7, 8, 9]}
],
}
})
</script>
</html></pre><div class="contentsignin">ログイン後にコピー</div></div>
単純なリスト
単純なリストの場合、 # を使用するよりも key を使用しない方が良い場合があります。 ## key
の場合、出力DOM コンテンツの走査が非常に単純であるか、意図的にパフォーマンスを向上させるためのデフォルトの動作。以下の例では、
key を使用せずにリストを更新すると、レンダリング速度が速くなっていることがわかります。
key が存在しない場合は、その場でリストが直接再利用されます。元のノードの要素は変更されず、要素はその場で再利用され、コンテンツは
5、
6、
7、
8## に更新されます。 # 、 9
、 10
、および 2 つのノード 11
と 12
が追加され、 key
が存在します。 次に、元の 1
、2
、3
、4
ノードが削除され、5
、6
ノードは保持され、7
、8
、9
、10
、11
が追加されます。 . 12
6 ノード、DOM
の追加と削除には時間がかかるため、key
を使用しない方が高速です。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// 没有key的情况下
console.time();
vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12];
vm.$nextTick(() => console.timeEnd());
// default: 2.193056640625ms</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// 存在key的情况下
console.time();
vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12];
vm.$nextTick(() => console.timeEnd());
// default: 3.2138671875ms</pre><div class="contentsignin">ログイン後にコピー</div></div>
インプレース再利用は副作用を引き起こす可能性があります。ドキュメントには、インプレース再利用のデフォルト モードは効率的であると記載されていますが、これはサブコンポーネントの状態や一時的な状態に依存しないアプリケーションにのみ適しています。 DOM
フォーム入力値などのステータスのリストレンダリング出力。 <p>在不设置<code>key
的情况下,元素中没有与数据data
绑定的部分,Vue
会默认使用已经渲染的DOM
,而绑定了数据data
的部分会进行跟随数据渲染,假如操作了元素位置,则元素中未绑定data
的部分会停留在原地,而绑定了data
的部分会跟随操作进行移动,在下面的例子中首先需要将两个A
之后的输入框添加数据信息,这样就制作了一个临时状态,如果此时点击下移按钮,那么不使用key
的组中的输入框将不会跟随下移,且B
到了顶端并成为了红色,而使用key
的组中会将输入框进行下移,且A
依旧是红色跟随下移。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>就地复用</title> </head> <body> <p id="app"> <h3>采用就地复用策略(vuejs默认情况)</h3> <p v-for='(p, i) in persons'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> <h3>不采用就地复用策略(设置key)</h3> <p v-for='(p, i) in persons' :key='p.id'> <span>{{p.name}}<span> <input type="text"/> <button @click='down(i)' v-if='i != persons.length - 1'>下移</button> </p> </p> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script> new Vue({ el: '#app', data: { persons: [ { id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 3, name: 'C' } ] }, mounted: function(){ // 此DOM操作将两个A的颜色设置为红色 主要是为了演示原地复用 document.querySelectorAll("h3 + p > span:first-child").forEach( v => v.style.color="red"); }, methods: { down: function(i) { if (i == this.persons.length - 1) return; var listClone = this.persons.slice(); var one = listClone[i]; listClone[i] = listClone[i + 1]; listClone[i + 1] = one; this.persons = listClone; } } }); </script> </body> </html> <!-- 源于 https://www.zhihu.com/question/61078310 @霸都丶傲天 有修改-->
复杂列表
使用key
不仅能够避免上述的原地复用的副作用,且在一些操作上可能能够提高渲染的效率,主要体现在重新排序的情况,包括在中间插入和删除节点的操作,在下面的例子中没有key
的情况下重新排序会原地复用元素,
但是由于v-if
绑定了data
所以会一并进行操作,在这个DOM
操作上比较消耗时间,而使用key
得情况则直接复用元素,v-if
控制的元素在初次渲染就已经决定,在本例中没有对其进行更新,所以不涉及v-if
的DOM
操作,所以在效率上会高一些。
console.time(); vm.complexListWithoutKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); vm.$nextTick(() => console.timeEnd()); // default: 4.100244140625ms
console.time(); vm.complexListWithKey = [ {id: 3, list: [7, 8, 9]}, {id: 2, list: [4, 5, 6]}, {id: 1, list: [1, 2, 3]}, ]; vm.$nextTick(() => console.timeEnd()); // default: 3.016064453125ms
以上がVueにおけるキーの役割の詳細コード説明例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。