ホームページ  >  記事  >  ウェブフロントエンド  >  フロントエンド開発者は、Web ページがどのようにレンダリングされるかを知る必要があります

フロントエンド開発者は、Web ページがどのようにレンダリングされるかを知る必要があります

伊谢尔伦
伊谢尔伦オリジナル
2016-11-29 09:35:502134ブラウズ

【編集者注】実際、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

ただし、前述したように、要素のプロパティを変更すると強制リフローがトリガーされます。この動作は、要素のプロパティにアクセスするコード行を上記のコード ブロックに追加すると発生します。

var $body = $('body'); $body.css('padding', '1px'); // プロパティの読み取り、強制リフロー $body .css('color', 'red'); $body.css('margin', '2px');

その結果、リフローが 2 回発生します。したがって、Web ページのパフォーマンスを最適化するには、要素属性にアクセスする操作をグループ化する必要があります。 (JSBin で詳細な例を見つけることができます)

場合によっては、強制リフローをトリガーする必要があります。たとえば、同じ属性 (左マージンなど) を同じ要素に 2 回割り当てる必要があります。最初はアニメーションなしで 100px に設定する必要があります。次に、トランジションアニメーションを介して50pxに変更する必要があります。この例は JSbin ですぐに実行できますが、ここではさらに詳しく説明します。

まず、トランジション効果を備えた CSS クラスを作成します。 -left 1sease-out;transition: margin-left 1sease-out; }

次に続行します: // デフォルトで「has-transition」クラスを持つ要素 var $targetElem = $('#targetElemId' );

// 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);

しかし、この実行は機能しません。すべての変更はキャッシュされ、コード ブロックの最後でのみ実行されます。必要なのは強制的な並べ替えであり、これは次の変更で実現できます:

// 遷移クラスを削除 $(this).removeClass('has-transition');

// 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);

これで、コードは期待どおりに実行されます。 ...スタイルはタグ内に含める必要があり、スクリプト コードはタグの最後に追加する必要があります。

CSS セレクターを可能な限り単純化して最適化し (この最適化方法は、CSS プリプロセッサを使用する開発者によってほぼ一律に無視されます)、ネストを最小限に抑えます。 CSS セレクターのパフォーマンス ランキングです (最速から順に)

1. 识别器:#id
2. 类:.class
3. 标签:div
4. 相邻兄弟选择器:a + i
5. 父类选择器:ul> li
6. 通用选择器:*
7. 属性选择:input[type="text"]
8. 伪类和伪元素:a:hover

ブラウザはセレクターを右から左に処理するため、右端のセレクターが最も高速である必要があることを覚えておいてください: #id または .class: div * {... } // 悪い .list li {...} // 悪い .list-item {...} // 良い #list .list-item {... } // 良い * 1. スクリプト コードでは、reduce可能な限り DOM 操作を実行します。再利用する場合は、要素の属性やオブジェクトを含むすべてをキャッシュします。複雑な操作を実行する場合は、後で DOM に追加できる「分離」要素を使用することをお勧めします (いわゆる「分離」要素は、DOM から分離され、メモリにのみ保存される要素です)。

2. jQuery を使用して要素を選択する場合は、jQuery セレクターのベスト プラクティスに従ってください。

3. 要素のスタイルを変更するには、「class」属性を変更することが有効な方法の一つです。この変更を実行するときは、DOM レンダリング ツリーの深部にあるほど良いでしょう (ロジックをプレゼンテーションから分離するのにも役立ちます)。

4. 絶対位置または固定位置を持つ要素にのみアニメーション効果を追加するようにしてください。

5. スクロールを使用する場合は、複雑なホバー アニメーションを無効にします (たとえば、ホバー以外のクラスを追加します)。読者はこの問題に関する記事を読むことができます。

さらに詳しく知りたい場合は、次の 2 つの記事もお読みください:

1、ブラウザの仕組み?

2、レンダリング: 再ペイント、リフロー/再レイアウト、再スタイル

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。