JavaScriptがDOMツリーの構築にどのように影響するかについて詳しく説明します。

JavaScriptがDOMツリーの構築にどのように影響するかについて詳しく説明します。

ドキュメント オブジェクト モデル (DOM)

ドキュメント オブジェクト モデル (DOM) は、Web ページをスクリプトまたはプログラミング言語に接続します。 DOM モデルは、論理ツリーを持つドキュメントを表します。ツリーの各ブランチはノードで終了し、各ノードにはオブジェクトが含まれます。 DOM メソッドを使用すると、プログラムでツリーにアクセスして、ドキュメントの構造、スタイル、コンテンツを変更できます。ノードはイベント ハンドラーに関連付けることができ、イベントがトリガーされるとイベント ハンドラーが実行されます。
ネットワークからレンダリング エンジンに送信された HTML ファイルのバイト ストリームは、レンダリング エンジンが直接理解することはできないため、レンダリング エンジンが理解できる内部構造に変換する必要があります。この構造が DOM です。 DOM は HTML ドキュメントの構造化された表現を提供します。レンダリング エンジンでは、DOM には 3 つのレベルの機能があります。

  • ページの観点から見ると、DOM はページを生成するための基本的なデータ構造です。
  • JavaScript スクリプトの観点から見ると、DOM は JavaScript スクリプト操作用のインターフェイスを提供します。このインターフェイスを通じて、JavaScript は DOM 構造にアクセスし、ドキュメントの構造、スタイル、およびコンテンツを変更できます。
  • セキュリティの観点から見ると、DOM は安全な防御線であり、一部の安全でないコンテンツは DOM 解析フェーズでブロックされます。

簡単に言うと、DOM は HTML を表す内部データ構造です。Web ページと JavaScript スクリプトを接続し、安全でないコンテンツをフィルタリングします。

DOM と JavaScript

DOM はプログラミング言語ではありませんが、DOM がなければ、JavaScript 言語には Web ページ、XML ページ、および関連する要素の概念やモデルが存在しません。ドキュメント全体、ドキュメント ヘッダー、ドキュメント内の表、表ヘッダー、表内のテキストなど、ドキュメント内のすべての要素は、ドキュメントが属するドキュメント オブジェクト モデル (DOM) の一部であるため、DOM と JavaScript などのスクリプト言語を使用してアクセスおよび操作できます。

当初、JavaScript と DOM は絡み合っていましたが、最終的には 2 つの別個のエンティティに進化しました。 JavaScript は DOM に保存されているコンテンツにアクセスして操作できるため、次のような近似式を書くことができます。

API (Web または XML ページ) = DOM + JS (スクリプト言語)

DOM と JavaScript

DOMツリーの生成方法

レンダリング エンジン内には、HTML バイト ストリームを DOM 構造に変換する役割を持つ HTML パーサーと呼ばれるモジュールがあります。
HTML パーサーは、ドキュメント全体が読み込まれるまで解析を待たずに、HTML ドキュメントが読み込まれると同時に解析を行います。HTML パーサーは、ネットワーク プロセスが読み込むデータと同じ量のデータを解析します。

プロセス: ネットワーク プロセスは、応答ヘッダーを受信すると、応答ヘッダーの content-type フィールドに基づいてファイルの種類を判断します。たとえば、content-type の値が "text/html" の場合、ブラウザーはこれが HTML タイプのファイルであると判断し、この判断に基づいて対応する解析エンジンを選択し、要求のレンダリング プロセスを選択または作成します。レンダリング プロセスの準備が整うと、ネットワーク プロセスとレンダリング プロセスの間に共有データ パイプラインが確立されます。ネットワーク プロセスはデータを受信すると、それをこのパイプラインに投入し、レンダリング プロセスはパイプラインのもう一方の端からデータを継続的に読み取り、同時に読み取ったデータを HTML パーサーに送信します。

このパイプラインは「水道管」として考えることができます。ネットワーク プロセスによって受信されたバイト ストリームは、水のようにこの「水道管」に流れ込み、「水道管」のもう一方の端はレンダリング プロセスの HTML パーサーであり、バイト ストリームを動的に受信して DOM に解析します。

図からわかるように、バイト ストリームから DOM への変換には 3 つの段階が必要です。

HTML 解析の 3 つの段階

最初の段階では、バイト ストリームはトークナイザーを通じてトークンに変換されます。

HTML の解析も同様です。トークナイザーを介してバイト ストリームをトークンに変換する必要があります。トークンはタグ トークンとテキスト トークンに分割されます。 HTML コードの字句解析によって生成されたトークンを下図に示します。

図からわかるように、タグトークンは StartTag と EndTag に分かれています。

2番目の段階では、トークンをDOMノードに解析します。

HTML パーサーはトークン スタック構造を維持します。これは主にノード間の親子関係を計算するために使用されます。最初の段階で生成されたトークンは、このスタックに順番にプッシュされます。具体的な処理ルールは次のとおりです。

  • StartTag トークンがスタックにプッシュされると、HTML パーサーはトークンの DOM ノードを作成し、そのノードを DOM ツリーに追加します。その親ノードは、スタック内の隣接する要素によって生成されたノードです。
  • トークナイザーがテキスト トークンを解析すると、テキスト ノードが生成され、DOM ツリーに追加されます。テキスト トークンはスタックにプッシュする必要はなく、その親ノードはスタックの現在の最上位トークンに対応する DOM ノードです。
  • トークナイザーが EndTag div などの EndTag タグを解析する場合、HTML パーサーはトークン スタックの最上部の要素が StarTag div であるかどうかを確認します。そうである場合、スタックから StartTag div がポップされ、div 要素の解析が完了したことが示されます。

トークナイザーによって生成された新しいトークンは継続的にプッシュおよびポップされ、トークナイザーがすべてのバイト ストリームのトークン化を完了するまで解析プロセス全体が続行されます。

3番目の段階はDOMツリーにDOMノードを追加することです

作成した DOM ノードをドキュメントに追加して、DOM ツリーを形成します。

HTML解析プロセスの詳細な説明

HTML パーサーが動作を開始すると、デフォルトでドキュメントをルートとして空の DOM 構造を作成し、StartTag ドキュメント トークンをスタックの一番下にプッシュします。次に、トークナイザーによって解析された最初の StartTag html トークンがスタックにプッシュされ、次の図に示すように、html DOM ノードが作成されてドキュメントに追加されます。

次に、StartTag body と StartTag div が同じプロセスに従って解析されます。トークン スタックと DOM の状態は次の図に示されています。

次に解析されるのは、最初の div のテキスト トークンです。レンダリング エンジンはトークンのテキスト ノードを作成し、トークンを DOM に追加します。その親ノードは、次の図に示すように、現在のトークン スタックの最上位要素に対応するノードです。

次に、トークナイザーは最初の EndTag div を解析します。この時点で、HTML パーサーはスタックの一番上の要素が StartTag div であるかどうかを判断します。そうである場合、次の図に示すように、StartTag div がスタックの一番上からポップされます。

同じルールに従うと、最終結果は次の図のようになります。

上記の紹介を通じて、DOM がどのように生成されるかはすでにご存知だと思います。ただし、実際の運用環境では、HTML ソース ファイルには CSS や JavaScript だけでなく、画像、音声、動画などのファイルも含まれるため、処理プロセスは上記のデモよりもはるかに複雑になります。ただし、この単純なデモ生成プロセスを理解すると、より複雑なシナリオを分析できるようになります。

JavaScript が DOM 生成に与える影響

ページに JavaScript スクリプトが含まれている場合、またはスクリプト ファイルをインポートする場合、このスクリプトの解析プロセスは上記のプロセスとは少し異なります。
スクリプト タグの前までの解析プロセスはすべて前述のとおりです。ただし、スクリプト タグまで解析すると、レンダリング エンジンはこれがスクリプトであると判断します。この時点で、HTML パーサーは DOM 解析を一時停止し、JavaScript エンジンが介入します。これは、JavaScript スクリプトが現在生成されている DOM 構造を変更する必要がある可能性があるためです。

スクリプトが JavaScript ファイル経由でロードされる場合は、まず JavaScript コードをダウンロードする必要があります。ここでは、ダウンロード環境に特別な注意を払う必要があります。JavaScript ファイルのダウンロード プロセスは DOM 解析をブロックし、ダウンロードには通常非常に時間がかかり、ネットワーク環境や JavaScript ファイルのサイズなどの要因によって影響を受けるためです。

スクリプトが直接埋め込まれた JavaScript スクリプトの場合は、直接実行されます。

JavaScript スクリプトが DOM 内の div のコンテンツを変更すると、スクリプトの実行後に解析された div ノードのコンテンツも変更されます。スクリプトが実行されると、HTML パーサーは解析プロセスを再開し、最終的な DOM が生成されるまで後続のコンテンツの解析を続けます。

もう 1 つの状況は、JavaScript コードが出現する場合、ページの CSS スタイルを変更するステートメントが CSSOM を操作するために使用されるため、JavaScript を実行する前に、JavaScript ステートメントより上のすべての CSS スタイルをまず解析する必要があることです。したがって、コード内で外部 CSS ファイルを参照している場合は、JavaScript を実行する前に、外部 CSS ファイルがダウンロードされ、解析されて CSSOM オブジェクトが生成されてから、JavaScript スクリプトを実行する必要があります。

JavaScript コードを解析する前は、JavaScript エンジンは JavaScript が CSSOM を操作するかどうかを認識しません。そのため、レンダリング エンジンは JavaScript スクリプトに遭遇すると、スクリプトが CSSOM を操作するかどうかに関係なく、CSS ファイルをダウンロードして解析し、JavaScript スクリプトを実行します。したがって、JavaScript スクリプトはスタイルシートに依存します。

上記の分析から、JavaScript は DOM 生成をブロックし、スタイル ファイルは JavaScript 実行をブロックすることがわかります。そのため、実際のプロジェクトでは、JavaScript ファイルとスタイル シート ファイルに注意する必要があります。不適切な使用はページのパフォーマンスに影響します。

解析中の最適化

ページのブロックを防ぐために、Chrome ブラウザでは多くの最適化が行われていますが、主な最適化の 1 つは事前解析操作です。レンダリング エンジンはバイト ストリームを受信すると、事前解析スレッドを開始し、HTML ファイルに含まれる JavaScript、CSS、およびその他の関連ファイルを解析します。関連ファイルを解析した後、事前解析スレッドはこれらのファイルを事前にダウンロードします。

DOM 解析に戻ると、JavaScript スレッドを導入すると DOM がブロックされることはわかっていますが、CDN を使用して JavaScript ファイルの読み込みを高速化し、JavaScript ファイルのサイズを圧縮するなど、これを回避するための関連する戦略がいくつかあります。また、JavaScript ファイルに DOM 関連のコードがない場合、コードに async または defer をマークすることで、JavaScript スクリプトを非同期で読み込むように設定できます。使い方は次のとおりです。

<script async type="text/javascript" src='foo.js'></script>
<script defer type="text/javascript" src='foo.js'></script>

async と defer はどちらも非同期ですが、いくつか違いがあります。async でマークされたスクリプト ファイルは読み込まれるとすぐに実行されますが、defer でマークされたスクリプト ファイルは DOMContentLoaded イベントの前に実行する必要があります。

要約する

まず、DOM がどのように生成されるかを紹介し、次に DOM 生成プロセスに基づいて、JavaScript が DOM 生成にどのように影響するかを分析しました。 CSS と JavaScript の両方が DOM の生成に影響を与えることも言及されています。

DOM生成プロセス

HTML を解析するには、トークナイザーを介してバイト ストリームをトークンに変換する必要があります。

StartTag トークンがスタックにプッシュされると、HTML パーサーはトークンの DOM ノードを作成し、そのノードを DOM ツリーに追加します。トークナイザーがテキスト トークンを解析すると、テキスト ノードが生成され、DOM ツリーに追加されます。トークナイザーが EndTag タグを解析すると、HTML パーサーはトークン スタックの最上部の要素が StarTag div であるかどうかを確認します。そうである場合、StartTag div がスタックからポップされ、div 要素の解析が完了したことが示されます。

トークナイザーによって生成された新しいトークンは継続的にプッシュおよびポップされ、トークナイザーがすべてのバイト ストリームのトークン化を完了するまで解析プロセス全体が続行されます。

解析プロセス中に JavaScript コードが検出されると、HTML の解析は停止されます。js がスクリプトを通じて読み込まれる場合、まずスクリプトがダウンロードされてから実行されます。実行前に、CSS も解析されて CSSOM が生成されます。このプロセスは、DOM 全体が構築されるまで継続されます。

JavaScript が DOM ツリー構築に与える影響についての記事はこれで終わりです。JavaScript DOM ツリー構築に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript 学習概要 (I) ECMAScript、BOM、DOM (コア、ブラウザ オブジェクト モデル、ドキュメント オブジェクト モデル)
  • JavaScript DOMContentLoaded イベントのケーススタディ
  • JavaScript における BOM と DOM の詳細な説明
  • Java による XML ファイルの解析と JSON の変換方法 (DOM4j 解析)
  • JavaScript の contains には関数実装コード (拡張文字、配列、DOM) が含まれていますか?
  • JavaScript のドキュメント オブジェクト モデル (DOM)

<<:  Centos7 FFmpeg オーディオ/ビデオ ツールのインストールに関する簡単なドキュメント

>>:  MySQLは複数テーブル関連統計(サブクエリ統計)の例を実装します

推薦する

MySQL データベース設計 3 つのパラダイム例分析

3つのパラダイム1NF: フィールドは分離不可能です。 2NF: 主キーがあり、非主キー フィールド...

JavaScript を使用して動的な QQ 登録ページを作成する

目次1. はじめに1. 基本レイアウト2. 写真を自動的に切り替える3. コンテンツを追加する4. ...

MySQL 起動時に「サーバーは PID ファイルを更新せずに終了しました」というエラーが報告される理由の詳細な分析

多くの人が MySQL の起動時にこのエラーに遭遇しています。まず、このエラーの前提は、サービス ス...

503 サービス利用不可エラーの解決方法の説明

1. Webページを開くと503サービス利用不可が表示されますが、更新すると正常にアクセスできます。...

Mysql は null 値の first/last メソッドの例を実装します

序文MySQL が SQL SELECT コマンドと WHERE 句を使用してテーブルからデータを読...

MySQL の隠し列の詳細表示

目次1. 主キーが存在する2. 主キーはないが、一意のインデックスが存在する3. 共同主キーまたは共...

MySQLのGROUP BYステートメントを最適化する方法

MySQL で、id、a、b の 3 つのフィールドを持つ新しいテーブルを作成します。次のように、同...

MySQL の null (IFNULL、COALESCE、NULLIF) に関する知識ポイントのまとめ

この記事では、MySQL の null (IFNULL、COALESCE、NULLIF) に関連する...

select @@session.tx_read_only が DB に大量に出現するのはなぜですか?

問題を見つける上位の SQL ステートメントを取得すると、DB が大量のselect @@sessi...

Docker で Kong API Gateway をインストールして使用する詳細なチュートリアル

1 はじめにKong は単純な製品ではありません。この記事で言及されている Kong は主に Kon...

擬似分散グラフィックを実現するための VMware 構成 Hadoop チュートリアル

1. 実験環境シリアルナンバープロジェクトソフトウェアとバージョン1オペレーティング·システムCen...

Mysql は、デッドロック問題を解決するために kill コマンドを使用します (実行中の特定の SQL ステートメントを強制終了します)。

MySQL を使用して特定のステートメントを実行すると、データ量が多いためにデッドロックが発生し、...

js 実行コンテキストとスコープの概要

目次序文文章1. JavaScriptコードの実行プロセスに関連する概念2. 実行コンテキストと実行...

ウェブサイト上のWeiboコンポーネントの再設計の詳細な紹介(写真とテキスト)

前面に書かれたWeibo コンポーネントは、サードパーティのアクセス ユーザーが開発を必要とせずに ...