ホームページ ウェブフロントエンド Vue.js Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

Sep 23, 2022 pm 08:03 PM
vue.js vue3

vue一意の識別子としてインデックスを使用できないのはなぜですか? Vue が一意の識別子としてインデックスを使用できない理由については、次の記事で紹介していますので、ご参考になれば幸いです。

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

これには、ネイティブ JS の DOM 操作と仮想 DOM による最適化が含まれます。以下は 2 つの部分に分けて説明します。

1. 仮想 DOM

まず、dom ノードをネイティブに操作する方法を見てみましょう。ただし、ノードの変更によりブラウザは再配置と再描画操作を実行するため、DOM 操作に対するブラウザの応答は非常にエネルギーを消費します (## を参照) #ブラウザ レンダリング ページ プロセス )

nbsp;html>



    <meta>
    <meta>
    <meta>
    <title>Document</title>



    <div>
        <ul></ul>
    </div>
    <script>
        let ul = document.querySelector(&#39;ul&#39;)
        for (let i = 0; i < 3; i++) {
            let li = document.createElement(&#39;li&#39;)
            li.innerHTML = i + 1
            ul.appendChild(li)
        }
    </script>


ログイン後にコピー

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

また、多くの JS コードは要素を動的に変更してブラウザの再配置を引き起こしており、エネルギー消費が想像できます。一部のノードが変更された場合、それらの変更されたノードをローカルに再配置すると、パフォーマンスが大幅に節約されるのではないでしょうか? ? ? vue が導入した仮想 dom はこの方式を採用しており、以下は vue のコードです

nbsp;html&gt;



    <meta>
    <meta>
    <meta>
    <script></script>
    <title>Document</title>



    <div>
        <ul>
            <item></item>
        </ul>
        <button>change</button>
    </div>

    <script>
        new Vue({
            el: &#39;#app&#39;,
            data() {
                return {
                    list: [1, 2, 3]
                }
            },
            methods: {
                change() {
                    this.list.reverse()
                }
            },
            components: {
                item: {
                    props: [&#39;num&#39;],
                    template: `
            <div>
              {{num}}  
            
          `,
                    name: &#39;child&#39;
                }
            }
        })
    </script>


ログイン後にコピー

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

#変更ボタンをクリックしたとき

#ネイティブ js がこのような操作を行うと必然的に並び替えが発生しますが、ページは部分的に変更されるだけですが、Vue は仮想 dom を導入してから消費電力を大幅に節約できましたVue がインデックスを一意の識別子として使用できない理由の簡単な分析

それでは? それは仮想 DOM ですか?

vue では、レンダリング関数を実行する前に仮想ノード ツリーを取得し、その仮想ノード ツリーを使用してページをレンダリングできます。ページ dom ノードが動的に変更されると、レンダリング前に、新しく生成された仮想ノードが最後に生成された仮想ノードと比較され、異なる部分のみがレンダリングされます。各仮想ノードはオブジェクトであり、コンテナーのレイヤーの特性を記述します。以下は、vue コードの変更ボタンをクリックする前の仮想ノード ツリーです。
vndoe = {
    tag: 'ul',
    children: [
        { tag: 'li',key:0, children: [{ vnode: { text: '3' } }] },
        { tag: 'li',key:1, children: [{ vnode: { text: '2' } }] },
        { tag: 'li',key:2, children: [{ vnode: { text: '1' } }] }

    ]
}复制代码
ログイン後にコピー

変更をクリックすると、新しい仮想ノード ツリーが生成され、それと比較されます

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析比較後、差分のみが表示されます

では、2 つの仮想ノードの数の差を見つけるにはどうすればよいでしょうか?これには、vue ソース コードの差分アルゴリズムが関係します

#ライフサイクルがマウントされた後、データ ソースが変更される限り、ウォッチャー オブザーバーのコールバックはドライブビューの更新 vm._update(v_rander())Vue がインデックスを一意の識別子として使用できない理由の簡単な分析_update は、差分アルゴリズムで異なる

_patch_ 開始を見つけるために、_patch_ に vnode を生成します。



key は、差分アルゴリズムを作成するための一意の識別子です。より効率的 比較する必要がある 2 つのノードを正確に見つけます

2. では、なぜインデックスをキーとして使用できないのでしょうか

私たちはまだ前のコードを参照してください。 diff アルゴリズムでは、 key は一意の識別子です。 2 つの仮想ノード ツリーを比較すると、比較のために同じキー値が見つかります。 キー値が同じであることが判明した場合、データは異なります。内部が異なる場合、差分アルゴリズムは変更されたと判断し、再レンダリングします。実際には、位置が変更されただけです。これに一意の識別 ID を追加すると、
nbsp;html&gt;    <meta>    <meta>    <meta>    <script></script>    <title>Document</title>    <div>        <ul>            <item></item>        </ul>        <button>change</button>    </div>    <script>        new Vue({            el: &#39;#app&#39;,            data() {                return {                    list: [{                        n: 1,                        id: 0
                    }, {                        n: 2,                        id: 1
                    }, {                        n: 3,                        id: 2
                    }, ]
                }
            },            methods: {                change() {                    this.list.reverse()
                }
            },            components: {                item: {                    props: [&#39;num&#39;],                    template: `
            <div>
              {{num}}  
            
          `,                    name: &#39;child&#39;
                }
            }
        })  </script>复制代码
ログイン後にコピー

[変更] をクリックした後の仮想ノード ツリー

#diff アルゴリズムが比較対象として同じキー値を見つけ、キー値は同じだが内部のデータも同じであることが判明した場合同じように、再レンダリングはされませんが、位置が変更され、ブラウザの消費量が大幅に節約されます。そのため、キーとしてインデックスを使用すると、diff での最適化が失敗します (再利用性が低下し、仮想 Dom の本来の意図に違反します)

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

データ インデックスをキーとして削除することの欠点は、より明らかです

nbsp;html&gt;    <meta>    <meta>    <meta>    <script></script>    <title>Document</title>    <div>        <ul>            <li>                <item></item>            </li>        </ul>        <button>del</button>    </div>    <script>        new Vue({            el: &#39;#app&#39;,            data() {                return {                    list: [1, 2, 3]
                }
            },            methods: {                del() {                    this.list.splice(0, 1)
                }
            },            components: {                item: {                    template: &#39;<div>{{Math.random()}}&#39;
                }
            }
        })    </script>复制代码
ログイン後にコピー

#削除ボタンをクリックした後

Vue がインデックスを一意の識別子として使用できない理由の簡単な分析

データを削除すると、配列の特性により、残りのデータの添字インデックスとキーが -1、つまり 2 番目、3 番目に変更されるため、実際には最後の項目が削除されたことがわかりました。データキーは 1,2 から 0,1 に変更され、diff アルゴリズムはキー 0,1 のデータ内容が変更され、キー 3 の内容が削除されたとみなして、最初と 2 を再レンダリングします。 2番目のデータを削除し、3番目のデータを削除しますが、実際には削除します。最初のコンテンツ、2番目、3番目は変更されたキーの値です。 Vue は、サブコンポーネントのテキスト コンテンツを深く比較しません。オブジェクトの外側の層が変更されたことのみを認識できます。キーを使用して比較します。キーが一意でない場合、仮想 DOM ツリーが誤って操作され、正しくレンダリングされません。

(学習ビデオ共有: Web フロントエンド開発基本プログラミング ビデオ)

以上がVue がインデックスを一意の識別子として使用できない理由の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

vue3 プロジェクトで tinymce を使用する方法 vue3 プロジェクトで tinymce を使用する方法 May 19, 2023 pm 08:40 PM

vue3 プロジェクトで tinymce を使用する方法

vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 May 21, 2023 pm 03:16 PM

vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法

Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 May 20, 2023 pm 04:16 PM

Vue3 がマークダウンを解析し、コードのハイライトを実装する方法

Vue3 でページの部分的なコンテンツを更新する方法 Vue3 でページの部分的なコンテンツを更新する方法 May 26, 2023 pm 05:31 PM

Vue3 でページの部分的なコンテンツを更新する方法

Vue3 の再利用可能なコンポーネントの使用方法 Vue3 の再利用可能なコンポーネントの使用方法 May 20, 2023 pm 07:25 PM

Vue3 の再利用可能なコンポーネントの使用方法

DefineCustomElement を使用して Vue3 でコンポーネントを定義する方法 DefineCustomElement を使用して Vue3 でコンポーネントを定義する方法 May 28, 2023 am 11:29 AM

DefineCustomElement を使用して Vue3 でコンポーネントを定義する方法

Vue3 と Element Plus を使用して自動インポートを実装する方法 Vue3 と Element Plus を使用して自動インポートを実装する方法 May 22, 2023 pm 04:58 PM

Vue3 と Element Plus を使用して自動インポートを実装する方法

vue3 で ECharts コンポーネントをカプセル化する方法 vue3 で ECharts コンポーネントをカプセル化する方法 May 20, 2023 pm 03:22 PM

vue3 で ECharts コンポーネントをカプセル化する方法

See all articles