ホームページ  >  記事  >  ウェブフロントエンド  >  Vueにおけるキーの役割の詳細コード説明例

Vueにおけるキーの役割の詳細コード説明例

coldplay.xixi
coldplay.xixi転載
2020-07-11 17:43:282308ブラウズ

Vueにおけるキーの役割の詳細コード説明例

#Vue におけるキーの役割

key の特別な attribute は、主に Vue の仮想 DOM アルゴリズムで、古いものと新しい ## を比較するときに VNode を識別するために使用されます。 #ノード key が使用されない場合、Vue は動的要素を最小限に抑えるアルゴリズムを使用し、可能な限り同じタイプの要素を適切な場所で変更して再利用しようとします。代わりに ## を使用してください。 #key では、key の変更に基づいて要素の順序が並べ替えられ、key が存在しない要素が削除されます。さらに、同じ親要素を持つ子要素には一意の key が必要です。key を繰り返すとレンダリング エラーが発生します。 関連する学習の推奨事項:

JavaScript ビデオ チュートリアル

説明

##最初は公式ドキュメントの説明です。Vue

v-for

を使用してレンダリングされた要素リストを更新するとき、デフォルトでインプレース更新戦略が使用されます。データ項目が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、各要素をその場で更新し、各インデックス位置で正しくレンダリングされるようにします。このデフォルト モードは効率的ですが、子コンポーネントの状態や一時的な DOM 状態 (フォーム入力値など) に依存しないリスト レンダリング出力にのみ適しています。 Vue にヒントを与えて各ノードの ID を追跡し、既存の要素を再利用したり並べ替えたりできるようにするには、項目ごとに一意の key 属性 を提供する必要があります。出力 DOM のコンテンツの走査が非常に単純であるか、意図的にデフォルトの動作に依存している場合を除き、v-for を使用する場合は key 属性 を提供する可能性があります。パフォーマンスの向上のため。 簡単に言うと、リスト ループで key を使用する場合、

key

を使用して各ノードを一意に識別する必要があります。diffアルゴリズムは次のことを行うことができます。このノードを正しく識別し、ノードを直接操作するための正しい位置を見つけ、要素を可能な限り再利用します。key の役割は主に、仮想 DOM を効率的に更新することです。また、indexkey として使用することは推奨されません。データ変更時に Vue が強制的にコンポーネントを更新することを保証できるのは、その場での更新を避けるためだけです。これは副作用をもたらしますが、要素の最大限の再利用を保証することはできず、indexkey として使用すると、基本的に key を使用しない場合と同じデータ更新効果があります。 。

最初に Vue インスタンスを定義し、単純なリストと複雑なリストという 4 つのリストをレンダリングします。

key

を保持する場合と key を保持しない場合の更新とレンダリングの速度。このテストは、毎回 Console で実行するときに、Chrome 81.0 を使用します。コードを実行すると、ブラウザと Vue 自体の最適化の影響を回避するために、インターフェイスが最初に更新および再ロードされます。 <pre class="brush:js;toolbar:false;">&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Vue&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;p id=&quot;app&quot;&gt; &lt;ul&gt; &lt;li v-for=&quot;item in simpleListWithoutKey&quot; &gt;{{item}}&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt; &lt;li v-for=&quot;item in simpleListWithKey&quot; :key=&quot;item&quot; &gt;{{item}}&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt; &lt;li v-for=&quot;item in complexListWithoutKey&quot;&gt; &lt;span v-for=&quot;value in item.list&quot; v-if=&quot;value &gt; 5&quot;&gt;{{value}}&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;ul&gt; &lt;li v-for=&quot;item in complexListWithKey&quot; :key=&quot;item.id&quot;&gt; &lt;span v-for=&quot;value in item.list&quot; :key=&quot;value&quot; v-if=&quot;value &gt; 5&quot;&gt;{{value}}&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/p&gt; &lt;/body&gt; &lt;script src=&quot;https://cdn.staticfile.org/vue/2.2.2/vue.min.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt; var vm = new Vue({ el: &amp;#39;#app&amp;#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]} ], } }) &lt;/script&gt; &lt;/html&gt;</pre>単純なリスト

単純なリストの場合、 # を使用するよりも key を使用しない方が良い場合があります。 ## key

の場合、出力

DOM コンテンツの走査が非常に単純であるか、意図的にパフォーマンスを向上させるためのデフォルトの動作。以下の例では、key を使用せずにリストを更新すると、レンダリング速度が速くなっていることがわかります。key が存在しない場合は、その場でリストが直接再利用されます。元のノードの要素は変更されず、要素はその場で再利用され、コンテンツは 5678## に更新されます。 # 、 910 、および 2 つのノード 1112 が追加され、 key が存在します。 次に、元の 1234 ノードが削除され、56 ノードは保持され、7891011 が追加されます。 . 12 6 ノード、DOM の追加と削除には時間がかかるため、key を使用しない方が高速です。 <pre class="brush:js;toolbar:false;">// 没有key的情况下 console.time(); vm.simpleListWithoutKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() =&gt; console.timeEnd()); // default: 2.193056640625ms</pre><pre class="brush:js;toolbar:false;">// 存在key的情况下 console.time(); vm.simpleListWithKey = [5, 6, 7, 8, 9, 10, 11, 12]; vm.$nextTick(() =&gt; console.timeEnd()); // default: 3.2138671875ms</pre>インプレース再利用は副作用を引き起こす可能性があります。ドキュメントには、インプレース再利用のデフォルト モードは効率的であると記載されていますが、これはサブコンポーネントの状態や一時的な状態に依存しないアプリケーションにのみ適しています。 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=&#39;(p, i) in persons&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p> 

 <h3>不采用就地复用策略(设置key)</h3>
 <p v-for=&#39;(p, i) in persons&#39; :key=&#39;p.id&#39;>
 <span>{{p.name}}<span> 
 <input type="text"/> 
 <button @click=&#39;down(i)&#39; v-if=&#39;i != persons.length - 1&#39;>下移</button>
 </p>

 </p>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
 <script>
 new Vue({
 el: &#39;#app&#39;,
 data: {
 persons: [
 { id: 1, name: &#39;A&#39; },
 { id: 2, name: &#39;B&#39; },
 { id: 3, name: &#39;C&#39; }
 ]
 },
 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-ifDOM操作,所以在效率上会高一些。

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 サイトの他の関連記事を参照してください。

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