【編集者注】実際、Web ページのレンダリングに関する記事は数多くありますが、関連情報が散在しており、議論はあまり完全ではありません。このトピックについて一般的に理解したいのであれば、まだ多くのことを学ばなければなりません。そこで、ウェブ開発者のAlexander Skutinは記事を書くことにしました。彼は、この記事が初心者を助けるだけでなく、知識構造を更新したい上級フロントエンド開発者にとっても有益であると信じています。元のアドレス
翻訳は次のとおりです:
Web ページのレンダリングは非常に早い段階で実行する必要があり、ページ レイアウトが完成したばかりの早い段階で実行することもできます。スタイルとスクリプトは Web ページのレンダリングに重大な影響を与えるためです。したがって、プロの開発者は、練習中にパフォーマンスの問題が発生することを避けるために、いくつかのテクニックを知っておく必要があります。
この記事では、ブラウザ内の詳細なメカニズムについては研究しませんが、いくつかの一般的なルールを提案します。結局のところ、ブラウザエンジンが異なれば動作も異なるため、ブラウザ機能に関する開発者の調査がより複雑になることは間違いありません。
ブラウザはどのようにして Web ページのレンダリングを完了しますか?
まず、Web ページをレンダリングするときのブラウザーのアクションを確認してみましょう:
サーバー側からの HTML コードに基づいてドキュメント オブジェクト モデル (DOM) を形成します
スタイルを読み込み、解析して CSS オブジェクト モデルを形成します。
ドキュメント オブジェクト モデルと CSS オブジェクト モデルの上に、レンダリングされるオブジェクトのセットで構成されるレンダリング ツリーを作成します (Webkit では、これらのオブジェクトはレンダラーまたはレンダリング オブジェクトと呼ばれ、Gecko では「フレーム」と呼ばれます)。レンダー ツリーはドキュメント オブジェクト モデルの構造を反映しますが、タグや display:none 属性などの非表示の要素は含まれません。レンダー ツリーでは、各テキスト文字列は独立したレンダラによって表されます。各レンダー オブジェクトには、対応する DOM オブジェクトまたはテキスト ブロックと計算されたスタイルが含まれます。言い換えれば、レンダー ツリーはドキュメント オブジェクト モデルを視覚的に表現したものです。
レンダリング ツリー上の各要素について、レイアウトと呼ばれるその座標を計算します。ブラウザはフロー アプローチを使用し、要素を 1 つのパスでレイアウトしますが、テーブル要素には複数のパスが必要です。
最後に、レンダリングツリー上の要素がブラウザ上に表示されるこのプロセスを「ペイント」と呼びます。
ユーザーが Web ページを操作するか、スクリプト プログラムが Web ページを変更すると、Web ページの内部構造が変更されるため、上記の操作の一部が繰り返し実行されます。
再描画
background-color (背景色)、border-color (境界線の色)、visibility (可視性)、ブラウザーなど、Web ページ内の要素の位置に影響を与えない要素のスタイルを変更する場合新しいスタイルで要素を再描画するだけです (これはスタイルの再描画または再構築です)。
リフロー
リフローまたは再配置は、変更がテキストの内容や構造、要素の位置に影響を与える場合に発生します。これらの変更は通常、次のイベントによってトリガーされます:
DOM 操作 (要素の追加、削除、変更、または要素の順序の変更)、
フォーム フィールド内のテキストの変更、
CSS プロパティの変更。
スタイルシートの追加または削除; 「クラス」のプロパティの変更; 疑似クラスのアクティブ化 (:hover)。 ブラウザはどのようにレンダリングを最適化しますか? ブラウザは、再描画/再構築を可能な限り変更された要素の領域に制限しようとします。たとえば、固定または絶対位置を持つ要素の場合、サイズ変更は要素自体とそのサブ要素にのみ影響しますが、静的に配置された要素のサイズ変更は後続のすべての要素のリフローをトリガーします。もう 1 つの最適化手法は、複数の JavaScript コードを実行するときに、ブラウザーがこれらの変更をキャッシュし、コードの実行終了後にこれらの変更を 1 つのパスで適用することです。たとえば、次のコードはリファクタリングと再描画のみをトリガーします:
var $body = $('body'); $body.css('padding', '1px'); // reflow, repaint $body.css('color', 'red'); // repaint $body.css('margin', '2px'); // reflow, repaint // only 1 reflow and repaint will actually happen
ただし、前述したように、要素のプロパティを変更すると強制リフローがトリガーされます。この動作は、要素のプロパティにアクセスするコード行を上記のコード ブロックに追加すると発生します。
// remove the transition class $targetElem.removeClass('has-transition'); // change the property expecting the transition to be off, as the class is not there // anymore $targetElem.css('margin-left', 100); // put the transition class back $targetElem.addClass('has-transition'); // change the property $targetElem.css('margin-left', 50);
// change the property $(this).css('margin-left', 100); // trigger a forced reflow, so that changes in a class/property get applied immediately $(this)[0].offsetHeight; // an example, other properties would work, too // put the transition class back $(this).addClass('has-transition'); // change the property $(this).css('margin-left', 50);
1. 识别器:#id 2. 类:.class 3. 标签:div 4. 相邻兄弟选择器:a + i 5. 父类选择器:ul> li 6. 通用选择器:* 7. 属性选择:input[type="text"] 8. 伪类和伪元素:a:hover