こんにちは、ジーピーオンライン(@gpol_tw)のWebエンジニア、ミキです!
DOM(ドム)は、HTMLを操作するために必須な知識であり、ユーザーの操作に応じて変化するWebサイトを制作する上で必要不可欠な技術です。
この記事では、DOMの基本について解説し、DOMに関連するイベント登録やローディング処理について、エンジニア向けに初心者がつまづきやすいポイントを紹介します。
フロントエンドの構築もおまかせください!
もくじ
DOMとは
DOMとはDocument Object Model(ドキュメントオブジェクトモデル)の略で、HTMLやXMLでマークアップされた文書を、JavaScriptなどのスクリプトからアクセス・操作できるようにするAPI(アプリケーションプログラミングインターフェース)です。
Webサイトを動的に変更したい場合、一般的にはJavaScriptを使いますが、JavaScriptだけではHTML要素を直接操作することはできません。
DOMを使用することで、それらが可能になり、ユーザーのクリックやスクロールなどの操作に応じて、サイトの内容を更新することが可能になります。
さらに、DOMはJavaScriptだけではなく、PythonやPHPなどの他のプログラミングの言語でも利用可能であり、操作するプログラミング言語には依存しない設計になっています。
「DOM」には2つの意味がある
「DOM」という用語は、2つの異なる意味を持っています。
1.規格(仕様)としての意味を持つ「Dom」
HTMLなどで作成された文書をどのように構造化し、どのようにアクセス・操作できるようにするかを定めたAPIの規格(仕様)のことです。
名前にも「モデル」が含まれている通り、ここでの「DOM」は概念であり、実体を持ちません。
このAPIの仕様は、現在「WHATWG(Web Hypertext Application Technology Working Group)」という技術者グループが主導して仕様を策定しています。
以前は「W3C(World Wide Web Consortium)」がDOMの標準化を担当をしていましたが、HTML5の仕様を巡る対立により、DOMやHTMLの標準化についてはWHATWGが主導権を握るようになりました。
2.実装されたAPIとしての意味を持つ「Dom」
「1」で説明した仕様に基づき、実際にDOMを生成・実装するのは各ブラウザです。
この実装されたものを「DOM」と呼び、HTMLなどの文書にアクセス・操作するためのAPIとして提供されます。
ブラウザは、HTML文書を解析し、「1」で策定されているAPIの仕様(DOM)に従って、「2」の実際のAPI(DOM)を実装する流れです。
そして、そのAPIを使用して開発者がJavaScriptで処理を記述することで、HTMLを動的に操作することが可能になります。
なぜ「DOM」が必要なのか?
DOMの仕様が策定される前は、各ブラウザが独自の仕様に基づいてHTMLを操作していました。そのため、同じJavaScriptコードが、各ブラウザごとで挙動が異なってしまうという問題が発生していました。
そこで、共通のDOM仕様を策定することで、各ブラウザがそれに準拠した実装をおこない、同じJavaScriptのコードが多くのブラウザで同じように動作するようになりました。
DOMの仕様書には、各ブラウザが実装するAPIのメソッド名や期待する結果が定義されていますが、具体的な実装方法については記載されておらず、各ブラウザがそれぞれの方法で実装をしています。
例えば、「querySelectorAll」メソッドの場合、DOMの仕様書では「ページ内のすべての指定した要素すべてを取得するメソッドである」と定義されており、各ブラウザはその通りの動作になるように実装をしています。
現在、主要なブラウザはDOMの標準仕様に準拠しており、開発者はブラウザごとの挙動の違いに悩まされることはなく開発を進めることができています。
※なお、2022年にサポートが終了したInternet Explorer(IE)は、DOMの対応が遅れていたため、他ブラウザと違う挙動を取ることが多くありました。そのため、JavaScriptのライブラリであるjQueryは、そういったブラウザで同じ動作を実現させるためのライブラリとしてよく使用されていました。
DOMの構造について
ブラウザがDOMを生成する際、HTMLを解析し、各HTML要素を操作しやすいようにツリー構造にします。
ここでは、生成されたDOMの構造と、それを操作するAPIの使い方について解説します。
ツリー構造とは
ブラウザはHTMLの文書を解析し、各HTML要素を「ノード」として管理します。これらのノードは親子関係を持つツリー構造として構成されます。
この階層的な構造により、例えばHTML要素のdivタグの中に、子要素としてpタグを追加するなどの操作が可能になります。
以下のようなHTMLを例に、DOMツリーの構造を見てみましょう。このHTMLをブラウザが解析すると、ブラウザは右側のようなDOMツリーを生成します。
最上位に「document」が存在しており、そこから分岐していく階層構造になります。
DOMツリーにはさまざまなノードの種類があり、例えば以下のように分類されます。
- 最上位の「document」は「Documentノード」
- HTMLタグの要素は「Elementノード」
- 要素内のテキストは「Textノード」
それぞれのノードは異なるメソッドを提供しており、そのAPIも異なります。
DOMノードの操作
DOMツリーの各ノードはオブジェクトとして表現され、そこに複数のAPIが定義されています。先述した3つのノード(Documentノード、Elementノード、Textノード)についてそれぞれの代表的なメソッドをご紹介します。
Documentノードのメソッド
Documentノードのオブジェクトでは全体の構造や要素を操作するためのAPIを提供しています。
Elementノードのメソッド
Elementノードのオブジェクトには、HTML要素を操作するためのメソッドを提供します。
例えば、テキストの変更や属性の取得・設定ができます。
Textノードのメソッド
Textノードはテキストコンテンツを取得、または設定できるメソッドを提供しています。
このように、DOMはツリー構造と各ノードのオブジェクトを通じて、HTML要素を操作する仕組みが提供されています。
DOMへのイベント登録
「addEventListener」メソッドを使うことで、ユーザーの操作によって発生するイベント(クリック、キーボードの入力など)の登録ができます。
このメソッドは、DocumentノードやElementノードなど、ほとんどのノードで使用可能です。
例えば、clickイベントを登録する場合は以下のように記述します。
イベント登録の注意点
JavaScriptでは非同期処理を使って、時間がかかる処理の完了を待ってからコンテンツを表示させたりすることが可能です。
例えば、画像をクリックした際にポップアップを表示し、拡大した画像を表示したいとします。その場合、下記のように「addEventListener」メソッドを使用してクリックイベントを記述します。
次に、実際にクリックする対象である画像を、2秒間待ってからWebページに設置されるようにします。指定した時間の後に処理を実行させたい場合はsetTimeout関数を使用します。
これで、2秒後に画像がWebサイト上に設置されました。ではこの状態で、追加された画像をクリックしてポップアップを表示してみましょう。
…と言いたいところですが、この状態だとポップアップは表示されません。
なぜなら、最初に記述したクリックイベントは、最初の時点で存在していたDOM要素にしか適用されないからです。
追加されたimgタグは、2秒後にDOMに追加されており、最初に記述したクリックイベントの設定は、最初の時点に存在しているDOM要素に対してのみ有効となります。
これを解決するには、「イベント委譲」をおこなう必要があります。
イベント委譲とは、親要素に対してイベントを登録することで、その子要素として追加された要素にもイベントを適用させることです。
このように、DOMノードに直接イベントを設定する場合、動的に追加された要素に対してはイベントが適用されないこともあるので注意が必要です。
JavaScriptのローディングイベント
JavaScriptには、ページの読み込みに関連するいくつかのイベント・メソッドが存在します。それぞれ発火するタイミングが異なるため、以下でその違いを説明します。
イベント発火タイミングの違い
loadイベント
loadイベントは、画像やスタイルシート、JavaScriptなどを含む、すべてのリソースの読み込みが完了した時点で発火します。DOMツリーの「document」と、それよりさらに上に存在している「window」ノードや、画像に対してloadイベントを登録できます。
DOMContentLoadedイベント
DOMContentLoadedイベントは、HTMLの文書が完全に読み込まれ、DOMツリーの生成が完了した時点で発火します。ただし、画像やスタイルシートなどの外部リソースの読み込みは待たずに発生します。DOMツリーのdocumentノードに対して登録できるイベントです。
DOMContentLoaded は、DOMの解析が完了した時点で発火するため、画像やスタイルシートがまだ読み込まれていなくても処理が開始されます。
これに対してload イベントは、すべてのリソースが読み込まれてから発火するため、ページのレイアウトが完了してから処理を開始する必要がある場合には、loadイベントを使用する必要があります。
jQueryのローディングメソッド
よく利用されるライブラリのひとつであるjQueryには、readyメソッドというイベントがあります。このメソッドは、上記のDOMContentLoadedイベントと同じタイミングで発火します。
readyメソッドは、DOMの解析が完了したタイミングで発生しますが、画像や外部リソースが読み込まれているかどうかは関係ありません。画像や外部リソースの読み込み後に処理をおこないたい場合には、loadイベントを使用する必要があります。
jQueryのreadyメソッドを使用する際の注意点
jQueryのreadyメソッドの中で、JavaScriptのloadイベントを記述する際には注意が必要です。以下のように記述すると、ブラウザによっては正しく実行されないことがあります。
それを回避するために、以下のように分けて記述することが推奨されます。
また、jQueryは複数のブラウザでの動作を統一させるために作られましたが、現在では主要なブラウザがDOMの標準仕様をサポートしているため、jQueryを使わなくてもJavaScriptで簡単にDOM操作やイベント処理がおこなえるようになっています。
まとめ
DOMはWebサイトの実装に欠かせない要素であり、HTMLをJavaScriptで操作するために必要不可欠な技術です。
DOMの仕組みを理解することで、効率的な操作が可能になり、エラー発生時にも迅速に原因を特定し対処しやすくなると思います。この記事の内容が少しでも役立つことを願っています。
Webサイトのエラー調査もおまかせください!
サービス資料をダウンロードいただけます
Web制作会社をお探しの方へ向けて、当社のサービス内容を簡単にダウンロードできる資料請求フォームをご用意いたしました。
▼資料内容(一部)
-ジーピーオンラインについて
-ジーピーオンライン3つの力
-サイト作りのポリシー
-品質管理
-サービス紹介・実績
WRITERミキ システムエンジニア
2019年に新卒として入社。キャンペーンサイトやコーポレートサイトの構築などを担当。フロントエンド・バックエンドの両方で活躍できるエンジニアを目指して、フロントエンドの知識習得や、PHPフレームワーク(Laravel)の勉強をしています。