vueバーチャルDOMの原理

3929 ワード

なぜバーチャルDOMが必要ですか?
フロントエンドの動作を抽象化すると、主にメンテナンス状態と更新図であり、ビューの更新とメンテナンス状態はDOM操作が必要である。実は近年、先端のフレームワークは主にDOM操作の複雑さを解放する方向に発展しています。
jsを実行するスピードはとても速くて、大量の操作DOMはとても遅くて、時々データを更新した後に再びページをレンダリングすることができて、このようにデータを変えていない地方でもDOMノードを再レンダリングしたことをもたらして、このようにしてとても大きい程度の上の資源の浪費をもたらしました。
jQueryが現れる前に、私達は直接DOM構造を操作します。この方法は複雑度が高く、互換性も低いです。jQueryの強大なセレクタと高度のカプセル化のAPIがあって、私達はDOMをもっと便利に操作することができて、jQueryは私達に互換性の問題を処理するように手伝って、同時にDOMの操作を簡単にならせます。
しかし、スマートなプログラマはここに満足することができません。様々なMVMフレームが生まれ、アングラーJS、avalon、vue.jsなどがあります。MVMはデータ双方向バインディングを使用して、DOMを操作する必要が全くなくなりました。状態を更新して、ビューは自動的に更新されます。ビューデータの状態を更新すると自動的に更新され、MVMは先端の開発効率を大幅に向上させるということができます。しかし、その大量のイベントバインディングによって、複雑なシーンでの実行性能が心配されています。開発効率と実行効率を両立させる案がありますか?これにより、Virtual DOM(仮想DOM)が導入される。
実際のDOMに対応するデータ構造をメモリ内で生成することを仮想DOMといいます。
データが変化すると、再レンダリングコンポーネントの最小値をインテリジェントに計算し、DOM動作に適用することができる。
Virtual DOMアルゴリズム
Virtual DOMというアルゴリズムです。いくつかのステップを含む:
1.JavaScriptオブジェクト構造でDOMツリーの構造を表します。そしてこの木で本当のDOMツリーを構築して、ドキュメントに挿入します。
2.状態が変更された場合、新たな対象樹を再構築する。新しい木と古い木を比較して、二つの木の違いを記録します。
3.2つの記録の違いをステップ1で構築された本当のDOMツリーに適用すると、ビューが更新されます。
Virtual DOMは本質的にJSとDOMの間でキャッシュしました。CPUとハードディスクと類比できます。ハードディスクがこんなに遅い以上、私達はそれらの間にキャッシュを入れます。
DOMが遅い以上、JSとDOMの間にキャッシュを入れます。CPU(JS)はメモリのみを操作し、最後に変更をハードディスク(DOM)に書き込みます。
virtual domとは、仮想ノードのことです。それはjsのObjectオブジェクトを通してDOM中のノードをシミュレートし、特定のrender方法によってリアルなDOMノードdomにレンダリングする。diffは、JSレベルの計算により、パッチオブジェクトというpatchオブジェクトを返し、特定の操作でpatchオブジェクトを解析し、ページの再レンダリングを完了する。

二つの仮想DOMツリーの違いを比較する。
2つのDOMツリーの違いを比較すると、Virtual DOMアルゴリズムの最も核心的な部分であり、これもいわゆるVirtual DOMのdiffアルゴリズムである。
二つのツリーの完全なdiffアルゴリズムは時間の複雑さがO(n^3)の問題である。しかし、先端の中では、階層を超えてDOM要素を移動することはめったにありません。したがって、Virtual DOMは同じレベルの元素のみを比較します。

上のdivは同じレベルのdivとしか比べられません。第二レベルは第二レベルとしか比べられません。このようにアルゴリズムの複雑さはO(n)に達することができる。
実際のコードでは、新旧の2つの木を深い優先で遍歴します。このように各ノードに一意のマークが付いています。

Virtual DOMアルゴリズムの実装
Virtual DOMアルゴリズムを実装するには主に3つの関数を使います。element、diff、patch。次に、実際に使用できます。下記のコードの通りです。

// 1.     DOM
var tree = el('div', {'id': 'container'}, [
  el('h1', {style: 'color: blue'}, ['simple virtal dom']),
  el('p', ['Hello, virtual-dom']),
  el('ul', [el('li')])
])

// 2.     DOM     DOM
var root = tree.render()
document.body.appendChild(root)

// 3.       DOM
var newTree = el('div', {'id': 'container'}, [
  el('h1', {style: 'color: red'}, ['simple virtal dom']),
  el('p', ['Hello, virtual-dom']),
  el('ul', [el('li'), el('li')])
])

// 4.       DOM    
var patches = diff(tree, newTree)

// 5.     DOM       
patch(root, patches)
diffアルゴリズム
3つの戦略でO(n^3)の複雑さをO(n)の複雑さに変換します。
  • 策略一(tree diff):
  • Web UIにおけるDOMノードの階層間の移動動作は特に少なく、無視できる。
  • 策略二:
  • 同じクラスの二つのコンポーネントを持ち、似たようなツリー構造を生成し、
    同じではない二つのコンポーネントを持ち、異なるツリー構造を生成する。
  • ポリシー三(element diff):
  • 同じ階層のサブノードのセットについては、一意のIDによって区別される。
    tree diff
    (1)PudateDepthにより、Virtual DOMツリーを階層制御する。
    (2)木の階層を比較し、2本の木は同じ階層のノードだけを比較する。ノードが存在しない場合、ノードとそのサブノードは完全に削除され、これ以上比較されない。
    (3)一回経るだけで、DOMツリー全体の比較ができます。

    diffは、同じ階層のノード位置変換のみを単純に考慮し、階層をまたぐ場合は、ノードを作成し、ノードを削除する動作のみを行う。

    上の図に示すように、Aをルートノードとするツリーは、移動ではなく、新たに作成されるので、DOMノードの階層間の動作を行わないように、実際に取り除かれ、DOMノードを追加するのではなく、CSSによってノードを非表示にすることができる。
    以上がevue仮想DOMの原理の詳細です。vueバーチャルDOMに関する資料は他の関連記事に注目してください。