私が見たリアクト(でのdevの話を- JSConf EU 2013再考ベストプラクティスを::リアクトピート・ハントを)とスピーカーは、モデルのダーティー・チェックが遅くなることが言及しました。しかし、仮想DOMは、ほとんどの場合、モデルよりも大きいはずなので、仮想DOM間の差分の計算は実際にはそれほど効率的ではありませんか?
私は本当に仮想DOMの潜在的な能力(特にサーバー側のレンダリング)が好きですが、すべての長所と短所を知りたいです。
私が見たリアクト(でのdevの話を- JSConf EU 2013再考ベストプラクティスを::リアクトピート・ハントを)とスピーカーは、モデルのダーティー・チェックが遅くなることが言及しました。しかし、仮想DOMは、ほとんどの場合、モデルよりも大きいはずなので、仮想DOM間の差分の計算は実際にはそれほど効率的ではありませんか?
私は本当に仮想DOMの潜在的な能力(特にサーバー側のレンダリング)が好きですが、すべての長所と短所を知りたいです。
回答:
私はvirtual-domモジュールの主要な作成者なので、あなたの質問に答えられるかもしれません。実際にここで解決する必要がある2つの問題があります
Reactでは、各コンポーネントに状態があります。この状態は、ノックアウトまたは他のMVVMスタイルのライブラリで見られる可能性があるオブザーバブルのようなものです。基本的に、React はこのデータがいつ変化するかを監視できるため、シーンをいつ再レンダリングするかを認識しています。ダーティチェックはオブザーバブルよりも低速です。定期的にデータをポーリングし、データ構造のすべての値を再帰的にチェックする必要があるためです。比較すると、状態に値を設定すると、一部の状態が変更されたことをリスナーに通知するため、Reactは状態の変更イベントをリッスンして、再レンダリングをキューに入れることができます。
仮想DOMは、DOMの効率的な再レンダリングに使用されます。これは、データのダーティーチェックとは実際には関係ありません。ダーティチェックの有無にかかわらず、仮想DOMを使用して再レンダリングできます。2つの仮想ツリー間のdiffの計算にはある程度のオーバーヘッドがありますが、仮想DOM diffは、データが変更されたかどうかではなく、DOMで何を更新する必要があるかを理解することです。実際、diffアルゴリズム自体はダーティチェッカーですが、代わりにDOMがダーティかどうかを確認するために使用されます。
状態が変化した場合にのみ、仮想ツリーを再レンダリングすることを目指しています。したがって、オブザーバブルを使用して状態が変化したかどうかを確認することは、不必要なツリーの差分が大量に発生する不要な再レンダリングを防止する効率的な方法です。何も変わっていなければ、何もしません。
仮想DOMを使用すると、シーン全体を再レンダリングする場合と同じようにコードを記述できます。背後で、DOMを更新して期待どおりの外観にするパッチ操作を計算する必要があります。したがって、仮想DOM diff / patchアルゴリズムはおそらく最適なソリューションではありませんが、アプリケーションを表現する非常に優れた方法を提供します。必要なものを正確に宣言するだけで、React / virtual-domがシーンをこのようにする方法を決定します。手動でDOMを操作したり、以前のDOMの状態について混乱したりする必要はありません。シーン全体を再レンダリングする必要もないため、パッチを適用するよりもはるかに効率が悪くなる可能性があります。
unnecessary re-renders
か?
this.state.cats = 99
としても、Angularが$ scopeツリーをダーティチェックするのと同じように、モデルの変更をチェックするためにダーティチェックが必要になります。これは2つの手法の速度の比較ではなく、バックボーンスタイルセッターを備えているため、Reactがダーティーチェックを行わないという単なる説明です。
最近、Reactのdiffアルゴリズムに関する詳細な記事をここで読みました:http : //calendar.perfplanet.com/2013/diff/。私が理解していることから、Reactを速くするものは次のとおりです:
ダーティチェックと比較した場合、IMOの主な違いは次のとおりです。
モデルのダーティチェック:ReactコンポーネントはsetState
、呼び出されるたびに明示的にダーティとして設定されるため、ここでは(データの)比較は必要ありません。ダーティチェックでは、(モデルの)比較は常に各ダイジェストループで行われます。
DOMの更新:DOMを変更するとCSSスタイル、レイアウトも適用および計算されるため、DOMの操作は非常にコストがかかります。不要なDOMの変更による節約時間は、仮想DOMの比較に費やされる時間よりも長くなる可能性があります。
2番目のポイントは、フィールドの数が多いモデルやリストが大きいモデルなど、重要なモデルではさらに重要です。複雑なモデルの1つのフィールド変更により、ビュー/テンプレート全体ではなく、そのフィールドに関連するDOM要素に必要な操作のみが発生します。
$scope.$digest
はダイジェストサイクルごとに複数回実行されるため、部分的な仮想DOMツリー比較の1回だけの完全なデータ比較に対して複数回の実行になります。
私は本当に仮想DOMの潜在的な能力(特にサーバー側のレンダリング)が好きですが、すべての長所と短所を知りたいです。
-OP
ReactだけがDOM操作ライブラリではありません。詳細な説明とベンチマークを含むAuth0の記事を読んで、代替案を理解することをお勧めします。あなたが尋ねたように、私はここで彼らの長所と短所を強調します:
React.jsの仮想DOM
長所
- 高速で効率的な「差分」アルゴリズム
- 複数のフロントエンド(JSX、ハイパースクリプト)
- モバイルデバイスで実行できるほど軽量
- たくさんの牽引力とマインドシェア
- Reactなしで(つまり、独立したエンジンとして)使用できます
短所
- DOMの完全なメモリ内コピー(メモリ使用量が多い)
- 静的要素と動的要素を区別しない
Ember.jsのグリマー
長所
- 高速で効率的な差分アルゴリズム
- 静的要素と動的要素の違い
- EmberのAPIと100%互換性があります(既存のコードを大幅に更新しなくてもメリットがあります)
- DOMの軽量のメモリ内表現
短所
- エンバーでのみ使用されることを意味します
- 利用可能なフロントエンドは1つのみ
インクリメンタルDOM
長所
- メモリ使用量の削減
- シンプルなAPI
- 多くのフロントエンドおよびフレームワークと簡単に統合(最初からテンプレートエンジンバックエンドとして意味)
短所
- 他のライブラリほど高速ではありません(これは議論の余地があります。以下のベンチマークを参照してください)
- マインドシェアとコミュニティの使用が少ない
ReactチームメンバーのSebastianMarkbågeからのコメントは次のとおりです。
Reactは、出力(これは既知のシリアライズ可能なフォーマット、DOM属性です)の差分を行います。つまり、ソースデータは任意の形式にすることができます。不変のデータ構造で、クロージャー内の状態にすることができます。
Angularモデルは参照透過性を保持しないため、本質的に変更可能です。既存のモデルを変更して、変更を追跡します。データソースが常に不変のデータまたは新しいデータ構造(JSON応答など)の場合はどうなりますか?
ダーティチェックとObject.observeは、クロージャスコープの状態では機能しません。
これら2つのことは、明らかに機能パターンを非常に制限しています。
さらに、モデルの複雑さが増すと、ダーティートラッキングを実行するのがますます高価になります。ただし、Reactのようにビジュアルツリーのみを比較すると、画面上に表示できるデータの量はUIによって制限されるため、それほど大きくなりません。上記のピートのリンクは、より多くのパフォーマンス上の利点をカバーしています。
Virtual Domは、reactによって発明されたのではありません。HTML domの一部です。軽量で、ブラウザ固有の実装の詳細から切り離されています。
仮想DOMは、Reactのローカルで単純化されたHTML DOMのコピーと考えることができます。これにより、Reactはこの抽象的な世界で計算を行い、「実際の」DOM操作をスキップできます。これは、多くの場合、ブラウザー固有の低速です。実際、DOMとVIRTUAL DOMの間に大きな違いはありません。
以下は、仮想Domが使用される理由です(ReactJSのソース仮想DOM)。
あなたがするとき:
document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
- ブラウザはHTMLを解析する必要があります
- elementIdの子要素を削除します
- DOM値を新しい値で更新します
- 親と子のCSSを再計算します
- レイアウトを更新します。つまり、各要素は画面上の正確な座標です
- Render Treeをトラバースし、ブラウザのディスプレイにペイントします
CSSおよび変更されたレイアウトの再計算は複雑なアルゴリズムを使用し、パフォーマンスに影響を与えます。
同様にDOMプロパティを更新します。値。アルゴリズムに従います。
ここで、DOMを10回直接更新すると、上記のすべてのステップが1つずつ実行され、DOMアルゴリズムの更新にはDOM値の更新に時間がかかると想定します。
これが、Real DOMが仮想DOMよりも遅い理由です。