参考記事:
なぜDOMのフロントエンド操作が最もパフォーマンスを消費するのか?
JS DOM 操作が非常にパフォーマンスを消費するのはなぜですか?
JavaScript DOM 操作がパフォーマンスに影響を与えるのはなぜですか?
JavaScriptでは、jsエンジンとレンダリングエンジン(ブラウザカーネル)が独立して実装されています。js を使用して DOM を操作する場合、それは基本的に、JS エンジンとレンダリング エンジンの間の「国境を越えた通信」になります。DOM を操作するたびに、境界を越える必要があります。国境を越える回数が増えると、明らかなパフォーマンスの問題が発生します。
DOM 操作がパフォーマンスに影響を与える主な理由は 2 つあります。
- ブラウザでは、DOM の実装と ECMAScript の実装が分離されています。たとえば、Chrome は WebKit の WebCore を使用して DOM とレンダリングを処理しますが、ECMAScript は V8 エンジンに実装されています。したがって、JavaScript コードを介して DOM インターフェイスを呼び出すことは、2 つの独立したモジュールの相互作用と同等です。同じモジュール内の呼び出しと比較して、このようなモジュール間の呼び出しのパフォーマンス損失は非常に大きくなります。
- DOM 操作では通常、ブラウザの再描画とリフロー (リフロー、再レイアウトとも呼ばれます) が発生しますが、再描画とリフローには非常にコストがかかります。
機構:
- ドキュメントのダウンロードからページのレンダリングまでのプロセスで、ブラウザは HTML ドキュメントを解析して DOM ツリーを構築し、CSS を解析して CSS ルール ツリー (CSSOM) を生成します。
- レンダリング プロセス中に、この問題が発生した場合、
<script>
レンダリングは停止され、JS コードが実行されます。ブラウザには GUI レンダリング スレッドと JS エンジン スレッドがあるため、予期しないレンダリング結果を防ぐために、これら 2 つのスレッドは相互排他的です。JavaScript の読み込み、解析、実行により、DOM の構築がブロックされます。 - 次に、DOM ツリーと CSS ルール ツリーに基づいてレンダリング ツリー (Render-Tree) が構築され、CSS はセレクターに基づいて HTML 要素を照合します。
display: none;
レンダリング ツリーには、各要素のサイズ、マージン、およびその他のスタイル属性が含まれます。レンダリング ツリーには、 に設定された非表示要素や、などの<head>
非表示要素は含まれません<script>
(ただし、visibility: hidden;
またはの要素についてopacity: 0;
は、画面スペースを占有するため、 に表示されます)。レンダーツリー)。最後に、ブラウザは各要素の座標とサイズに基づいて位置を計算し、これらの要素をページ上に描画します。
ブラウザーのレンダリングのメカニズムを理解すると、再描画とリフローについてより明確に理解できるようになります。
重绘
これは、色や背景色の変更など、ページの一部の部分を再描画する必要があるが、要素の位置やサイズは変更されていないことを意味します。回流
これは、要素の位置またはサイズが変更され、ブラウザがレンダリング ツリーを再計算する必要があることを意味します。その結果、レンダリング ツリーの一部または全体が変更されます。レンダリング ツリーが再確立された後、ブラウザは影響を受ける要素を再描画します。ページ。
ps:回流的代价比重绘的代价高很多,重绘不一定是因为回流,但回流一定会导致重绘。
リフローを引き起こす DOM 操作の例は次のとおりです。
- ページ初期化レンダリング
- 表示されている DOM 要素の追加、削除、変更、または移動
- CSS スタイルまたは DOM を変更して要素のコンテンツを変更し、DOM 要素のサイズを変更します。
- ブラウザウィンドウのサイズ変更とブラウザウィンドウのスクロール
- 要素内容の変更(文字量や画像サイズなど)
- スタイル属性を設定する
- いくつかのプロパティをクエリするか、いくつかのメソッドを呼び出す
DOM 操作がパフォーマンスに影響を与える主な理由は 2 つあります。
- ブラウザーで JavaScript コードを介してDOM インターフェイスを呼び出すことは、2 つの独立したモジュールの対話と同等です。この種のモジュール間の呼び出しでは、パフォーマンスの低下が比較的大きくなります。
- 通常、DOM 操作によりブラウザの再描画とリフローが発生しますが、再描画とリフローには非常にコストがかかります。