なぜ仮想DOMが必要なのでしょうか?仮想 DOM はブラウザのパフォーマンス問題を解決するために設計されています。たとえば、1 回の操作で 10 回の DOM 更新があった場合、仮想 DOM はすぐに DOM を操作するのではなく、これらの 10 回の更新の差分コンテンツをローカル JS オブジェクトに保存し、最後にこの JS オブジェクトを一度に DOM ツリーにアタッチしてから後続の操作を実行し、多くの不要な計算を回避します。簡単に言えば、仮想 DOM は単純な JS オブジェクトとして理解でき、タグ名 (tag)、属性 (attrs)、子要素オブジェクト (children) の少なくとも 3 つの属性が含まれます。
仮想 DOM が必要な理由は何ですか? ----- JS の計算パフォーマンスを、実際の DOM の操作によって消費されるパフォーマンスと交換することです。Vue は、VNode クラスを通じてさまざまな種類の仮想 DOM ノードをインスタンス化し、さまざまな種類のノードによって生成される属性の違いを学習します。いわゆるさまざまな種類のノードは本質的に同じであり、すべて VNode クラスのインスタンスですが、インスタンス化中に渡されるパラメーターが異なります。 ----- そして、更新が異なる DOM ノードを見つけることで、実際の DOM に対する最小限の操作でビューを更新するという目的が達成されました。古い VNode と新しい VNode を比較して違いを見つけるプロセスは、いわゆる DOM-Diff プロセスです。DOM-Diff アルゴリズムは、仮想 DOM 全体の中核です。 パッチVue では、DOM-Diff プロセスはパッチ プロセスと呼ばれます。パッチはパッチを意味し、アイデアを意味します。いわゆる古い VNode (odlNode) は、データが変更される前の対応する仮想 DOM ノードであり、新しい NVode は、データが変更された後にレンダリングされるビューに対応する仮想 DOM ノードです。したがって、生成された新しい VNode をベンチマークとして使用して、古い oldVNode と比較する必要があります。新しい VNode にノードがあり、古い oldVNode にない場合は、そのノードを古い oldVNode に追加します。新しい VNode になく、古い oldVNode にあるノードがある場合は、そのノードを古い oldVNode から削除します。古い VNode ノードと新しい VNode ノードの両方が存在する場合、新しい VNode が参照として使用され、古い oldVNode が更新されて、新しい VNode ノードと古い VNode ノードが同じになります。 パッチ全体はノードの作成に関するものです。新しい VNode は存在しますが、古いものはありません。古いoldVNodeに作成する ノードの削除: ノードが新しい VNode に存在せず、古い VNode に存在する場合は、古い VNode から削除します。 ノードの更新: 新しいノードと古いノードの両方が利用可能な場合は、新しい VNode が参照として使用され、古い oldVNode が更新されます。 子ノードを更新する /* 2 つの子ノード配列を比較するには、外側のループ newChildren と内側のループ oldCHildren 配列をループする必要があります。外側の newChildren 配列の各子ノードについて、内側の oldChildren 配列を調べて、同一の子ノードがあるかどうかを確認します*/ (i = 0 とします; i < newChildred.length; i++) { 定数 newChild = newChildren[i] (j = 0; j < oldChildren.length; j++) の場合 { 定数 oldChild = oldChildren[i] (新しい子 === 古い子) の場合 { // ... } } } 上記のプロセスでは、次の4つの状況が発生します。
ノードの更新は新しい Vnode に基づいて行い、古い oldVnode が新しい VNode と同じになるように古い oldVnode を操作する必要があることを繰り返し強調してきました。 アップデートは 3 つの部分に分かれています。VNodeとoldVNodeが両方とも静的ノードである場合、 前述したように、静的ノードはデータの変更とは関係がないため、すべてが静的ノードである場合は処理されずに直接スキップされます。 VNodeがテキストノードの場合 VNode がテキスト ノードである場合、つまりこのノードにプレーン テキストのみが含まれている場合は、oldVNode もテキスト ノードであるかどうかを確認するだけで済みます。テキスト ノードである場合は、2 つのテキストが異なるかどうかを比較します。テキストが異なる場合は、oldVNode のテキストを VNode のテキストと同じになるように変更します。oldVNode がテキスト ノードでない場合は、それが何であっても、setTextNode メソッドを直接呼び出してテキスト ノードに変更します。テキスト コンテンツは VNode と同じになります。 VNodeが要素ノードである場合、さらに次の2つのケースに分けられます。
// ノード更新関数 patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) { // vnode と oldVnode はまったく同じですか? そうであれば、プログラムを終了します if (oldVnode === vnode) { 戻る } const elm = vnode.elm = 古いVnode.elm //vnode と oldVnode は両方とも静的ノードですか? はいの場合はプログラムを終了します if (isTrue(vnode.isStatic) && isTrue(vnode.isStatic) && vnode.key === oldVnode.key && (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) { 戻る } 定数 oldCh = oldVnode.children 定数ch = vnode.children // vnode にテキスト属性がある場合、そうでない場合は if (isUndef(vnode.text)) { isDef(oldCh) と isDef(ch) のどちらが正しいか // 両方存在する場合は、子ノードが同じかどうかを判断します。異なる場合は、子ノードを更新します。if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly) } // vnodeの子ノードのみが存在する場合 else if (isDef(ch)) { /** * oldVnode にテキストがあるかどうかを判断します。 * ない場合は、Vnode の子ノードを実際の DOM に追加します。 * 場合は、DOM 内のテキストをクリアし、vnode の子ノードを実際の DOM に追加します。 * */ if (isDef(oldVnode.text)) nodeOps.setTextContext(elm, '') addVnodes(elm, null, ch, 0, ch.length - 1, 挿入されたVnodeQueue) } // oldnodeの子ノードのみが存在する場合 else if (isDef(oldCh)) { // DOM 内のすべての子ノードをクリアします。removeVnodes(elm, oldCh, 0, oldCh.length - 1) } // vnode と oldnode に子ノードがないが、oldnode にテキストがある場合 else if (isDef(oldVnode.text)) { nodeOps.setTextContext(elm, '') } // 上記の 2 つの判断は 1 つの文にまとめることができます。vnode にテキストも子ノードもない場合は、対応する oldnode にあるものをすべてクリアします。} else if (oldVnode.text !== vnode.text) { nodeOps.setTextContext(elm, vnode.text) } } 上記では、DOM-DIFF アルゴリズムである Vue のパッチについて学習しました。また、パッチ プロセスでは基本的に、ノードの作成、ノードの削除、ノードの更新という 3 つの処理が行われることがわかりました。 ノードの作成と削除は比較的簡単ですが、ノードの更新にはさまざまな状況に対応する必要があるため、より複雑なロジックが必要です。 更新プロセス中、9 つの Vnode すべてに子ノードが含まれる場合があります。子ノードを比較して更新するための追加ロジックがいくつかあります。そこで、この記事では、Vue で子ノードを比較する方法を学習します。 子ノードを更新する 新しい Vnode と古い Vnode が両方とも要素ノードであり、子ノードを含む場合、2 つのノード VNode インスタンスの chidlren 属性は、含まれている子ノード配列です。ループを介して 2 つの子ノードを比較します。外側のループは newChildren 配列、内側のループは oldChildren 配列です。各ループは外側の newChildren 配列の子ノードに対して実行され、内側の oldChildren 配列に移動して同じ子ノードがあるかどうかを確認します。 子ノードを作成する 子ノードが作成される位置は、すべての処理済みノードの後ではなく、すべての未処理ノードの前である必要があります。 処理されたノードの後に子ノードが挿入された場合、後で新しいノードを挿入すると、新しく追加された子ノードが台無しになってしまうからです。 子ノードを移動する 処理されていないすべてのノードが、移動する場所です。 子ノードの更新を最適化します。先ほど、新しい VNode と古い VNode が両方とも要素ノードであり、両方とも子ノードを含む場合、Vue は最初に外側のレイヤーで newChildren 配列をループし、次に内側のレイヤーで oldChildren 配列をループすることを紹介しました。外側の newChildren 配列で子ノードをループするたびに、内側の oldChildren 配列を調べて同一の子ノードがあるかどうかを確認し、最終的にさまざまな状況に応じてさまざまな操作を実行します。まだ最適化できる領域はあります。たとえば、子ノードの数が多い場合、ループ アルゴリズムの時間計算量は非常に大きくなり、パフォーマンスの向上にはつながりません。 方法:
前回の記事では、Vue における仮想 DOM と仮想 DOM のパッチ (DOM-Diff) 処理について紹介しました。仮想 DOM が存在するための必要条件は VNode が存在することですが、では VNode はどこから来るのでしょうか。 ユーザーが書いたテンプレートをコンパイルするとVNodeが生成される テンプレートのコンパイル:テンプレートコンパイルとは:ユーザーのテンプレートタグに記述されたネイティブ HTML に類似したコンテンツをコンパイルし、ネイティブ HTML のコンテンツを検索し、非ネイティブ HTML を検索します。一連の論理処理の後、レンダリング関数が生成されます。このレンダリング関数のプロセスをテンプレートコンパイルプロセスと呼びます。レンダリング関数はテンプレートコンテンツからVNodeを生成する 全体的なレンダリング処理、いわゆるレンダリング処理は、一連の処理を経て、ユーザーが作成したネイティブ HTML に似たテンプレートをビューに反映させるというものです。この処理については、すでに上で説明しました。 抽象構文木 AST:
具体的なプロセス:
テンプレート解析フェーズ: 正規表現を使用して、一連のテンプレート文字列を抽象構文木 AST に解析します。 最適化フェーズ: ASTをコンパイルし、静的ノードを見つけてマークする コード生成フェーズ: ASTをレンダリング関数に変換する テンプレートのコンパイルによってのみ、仮想 DOM とそれに続くビューの更新が可能になります。 要約するVue ソースコード解析と仮想 DOM に関するこの記事はこれで終わりです。Vue 仮想 DOM に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: IIS7~IIS8.5 サーバープロトコルヘッダーの削除または変更
>>: MySQL インフラストラクチャ チュートリアル: クエリ ステートメント実行プロセスの詳細な説明
<br />ページに <img src=""> が含まれ...
この記事では、マウスでカード内外のコンテンツを切り替えるためのjsの具体的なコードを紹介します。具体...
単一のテーブルをエクスポートするmysqldump -u ユーザー -p db名 テーブル名 >...
目次vue2の場合vue3ではセットアップに関する注意事項セットアップライフサイクルは、before...
今日、SQLトレーニングの質問バンクでこの質問を見ました。これは、非常に代表的なマルチテーブル変更の...
MySQL 5.7.20のインストールと設定方法のグラフィックチュートリアルをあなたと共有します1...
# には位置情報が含まれます。デフォルトのアンカーは #top で、これは Web ページの上部です...
なぜこれを使ったのか?それはポスターを作ることから始まりました。それは嵐の夜でした。 。 。さて、無...
GitHub アドレス: https://github.com/dmhsq/dmhsq-mysql-...
1. コンテナに入るdocker run [オプション] イメージ名 [起動コンテナに渡されるコマン...
目次概要ブロブBlob の動作BLOB ダウンロード ファイルブロブ画像のローカル表示BLOB ファ...
この記事では、例を使用して、MySQL クエリ ステートメントの簡単な操作を説明します。ご参考までに...
目次最近Reactを勉強していて、今は仕事でVueを使っています。学習の過程で、両者を比較して理解を...
1. システム環境yum updateアップグレード後のシステムバージョンは[root@yl-web...
1. 新旧ドメイン名のジャンプ適用シナリオ: ドメイン名ベースのリダイレクト。会社の古いドメイン名は...