メインコンテンツに移動

DOM操作とは?JavaScriptでWebページを動的に変更する仕組みを徹底解説

Webページは、HTMLだけで作成すると基本的には静的な情報を表示するものになります。見出し、本文、画像、リンク、表、フォームなどを配置することはできますが、ユーザーの操作に応じて画面内容を変更したり、入力内容をリアルタイムに反映したり、ボタンを押した瞬間に表示を切り替えたりするにはJavaScriptが必要になります。現代のWebサイトやWebアプリケーションでは、こうした動的な画面制御が当たり前のように使われています。

DOM操作とは、JavaScriptを使ってWebページの構造や内容をプログラムから変更する仕組みです。DOMはHTML文書をブラウザがオブジェクトのツリー構造として表現したものであり、JavaScriptからその要素を取得したり、テキストを書き換えたり、属性を変更したり、CSSクラスを追加したりできます。つまり、DOM操作はHTMLを読み込んだ後の画面を動的に変化させるための基本技術です。

たとえば、ボタンをクリックしたらメッセージを表示する、フォームに入力した内容をすぐにプレビューする、商品一覧をJavaScriptで追加する、エラーメッセージを表示する、タブを切り替える、モーダルを開くといった処理は、すべてDOM操作と深く関係しています。ReactやVue、Angularのようなフレームワークを使う場合でも、内部的にはDOMの更新が行われています。

本記事では、DOM操作の基本概念、DOMとは何か、DOMツリーの構造、JavaScriptとDOMの関係、要素の取得方法、内容変更、属性操作、スタイル変更、要素の追加と削除、イベント処理、DOM操作の問題点、仮想DOMとの違い、フレームワークとの関係、実務でのベストプラクティスまで体系的に解説します。

1. DOM操作とは?

DOM操作とは、JavaScriptからWebページのHTML構造を取得・変更・追加・削除する処理のことです。ブラウザはHTMLを読み込むと、その内容をDOMというツリー構造に変換します。JavaScriptはこのDOMにアクセスすることで、画面上の要素を変更できます。たとえば、見出しの文字を変える、ボタンにクラスを追加する、リストに新しい項目を挿入する、といった操作が可能です。

DOM操作は、フロントエンド開発の基礎となる重要な概念です。現在ではReactやVueなどのフレームワークがDOM更新を抽象化してくれることが多いですが、DOMの仕組みを理解していないと、イベント処理、レンダリング、パフォーマンス、フォーム制御、アクセシビリティなどを正しく理解しにくくなります。

主な特徴

項目内容
対象HTML文書の構造や要素
操作方法JavaScriptからDOM APIを利用
主な用途画面更新、イベント処理、要素追加、スタイル変更
関連技術HTML、CSS、JavaScript、ブラウザAPI
注意点過剰な操作はパフォーマンス低下につながる

1.1 DOMの概要

DOMは、Document Object Modelの略で、日本語では文書オブジェクトモデルと説明されます。HTMLやXMLの文書を、ブラウザがプログラムから扱いやすいオブジェクト構造として表現したものです。HTMLの各タグはDOM上では要素ノードとして扱われ、テキストや属性もそれぞれノードやプロパティとしてアクセスできます。

DOMがあることで、JavaScriptはHTMLを単なる文字列ではなく、構造を持ったオブジェクトとして扱えます。たとえば、document.querySelector()で特定の要素を取得し、その要素のテキストや属性を変更できます。DOMは、HTMLとJavaScriptをつなぐ重要な橋渡しの役割を持っています。

1.2 DOM操作の意味

DOM操作の意味は、ブラウザ上に表示されているWebページをJavaScriptで動的に変更することです。HTMLファイルに書かれている内容はページ読み込み時の初期状態にすぎず、JavaScriptによってその後の表示を変化させられます。これにより、Webページは単なる静的な文書ではなく、ユーザー操作に反応するアプリケーションとして振る舞えるようになります。

たとえば、ログインフォームで入力エラーを表示する場合、HTMLにあらかじめ全てのエラーメッセージを書いておくのではなく、JavaScriptで条件に応じてDOMへメッセージを追加します。これがDOM操作です。ユーザーの行動に合わせて画面を変える仕組みとして、DOM操作は非常に重要です。

1.3 なぜ必要なのか

DOM操作が必要な理由は、Webページにインタラクティブ性を持たせるためです。現代のWebサイトでは、ボタンを押す、フォームに入力する、メニューを開く、検索結果を表示する、通知を出す、タブを切り替えるなど、多くの操作が画面上で即座に反映されます。これらはDOM操作によって実現されています。

また、サーバーから取得したデータを画面に反映する場合にもDOM操作が必要です。APIから商品一覧や投稿一覧を取得し、それをHTML要素として表示する処理は、DOMの追加や変更を伴います。Webアプリケーションの動的なUIを作るうえで、DOM操作は避けて通れない基礎技術です。

2. DOMとは何か?

DOMとは、HTML文書をブラウザがツリー構造のオブジェクトとして表現したものです。HTMLのタグ、テキスト、属性などは、それぞれDOM上のノードとして扱われます。JavaScriptはこのDOMを通じて、HTML文書の内容や構造にアクセスできます。

HTMLはファイルとしてはテキストですが、ブラウザが表示するときには内部的に解析され、DOMツリーとして構築されます。JavaScriptはこのDOMツリーを操作することで、画面に表示されている要素を変更できます。DOMは、Webページをプログラムから操作可能にするための標準的な仕組みです。

2.1 Document Object Modelの定義

Document Object Modelは、文書をオブジェクトとして扱うためのモデルです。Webブラウザにおいては、HTML文書の各要素をオブジェクトとして表現し、それらをJavaScriptなどのプログラムから操作できるようにします。DOMによって、Webページの内容、構造、スタイルを動的に変更できます。

DOMは特定のプログラミング言語だけの機能ではなく、ブラウザが提供する標準的なAPIです。JavaScriptから利用されることが最も多いですが、概念としてはHTML文書を構造化して扱うための仕組みです。フロントエンド開発では、DOMを理解することがJavaScriptによる画面制御の基礎になります。

2.2 HTMLとの関係

HTMLはWebページの構造を記述するマークアップ言語です。見出し、段落、リンク、画像、フォームなどをタグで表現します。一方、DOMはそのHTMLをブラウザが読み込んだ後に生成するオブジェクト構造です。つまり、HTMLは元の文書であり、DOMはブラウザ内部で操作可能な形に変換された構造だと考えることができます。

HTMLとDOMは似ていますが、完全に同じではありません。JavaScriptによって要素が追加された場合、元のHTMLファイルには書かれていなくても、ブラウザ上のDOMには存在します。また、ブラウザがHTMLの不完全な記述を補正してDOMを構築する場合もあります。この違いを理解しておくと、開発者ツールでDOMを確認する際にも役立ちます。

2.3 ツリー構造としてのDOM

DOMはツリー構造として表現されます。最上位にはdocumentがあり、その下にhtml要素、さらにhead要素やbody要素が続きます。bodyの中にはheader、main、section、button、pなどの要素が階層的に配置されます。この親子関係を持つ構造がDOMツリーです。

ツリー構造であるため、ある要素の親要素、子要素、兄弟要素をたどることができます。JavaScriptでは、親ノードを取得したり、子要素を追加したり、特定の要素を削除したりできます。このツリー構造を理解することが、DOM操作を正しく行うための基本です。

3. DOMツリーの構造

DOMツリーは、HTML文書をノードの集合として表現した構造です。ノードには、要素ノード、テキストノード、属性ノード、コメントノードなどがあります。通常のDOM操作では、HTMLタグに対応する要素ノードを扱うことが多いですが、テキストや属性もDOMの一部です。

DOMツリーを理解すると、なぜ親要素から子要素へアクセスできるのか、なぜ要素を追加すると画面が変わるのか、なぜイベントが親要素へ伝播するのかが理解しやすくなります。DOM操作は、単に関数を覚えるだけでなく、この構造を意識することが重要です。

3.1 ノードの概念

ノードとは、DOMツリーを構成する一つ一つの要素です。HTMLタグに対応するものは要素ノード、タグの中の文字列はテキストノード、属性は属性ノードとして扱われます。たとえば、<p>Hello</p>というHTMLがある場合、pは要素ノードであり、Helloはテキストノードです。

JavaScriptでDOMを操作するとき、多くの場合は要素ノードを取得して処理します。しかし、childNodesのようなプロパティを使うと、テキストノードやコメントノードも含まれる場合があります。そのため、要素だけを扱いたい場合はchildrenquerySelectorなどを適切に使う必要があります。

3.2 親子関係

DOMツリーでは、要素同士に親子関係があります。たとえば、body要素の中にmain要素があり、main要素の中にsection要素があり、section要素の中にbutton要素がある場合、bodyはmainの親であり、buttonはsectionの子です。このような階層関係をたどることで、JavaScriptから目的の要素へアクセスできます。

親子関係は、要素の追加や削除でも重要です。新しい要素を画面に表示するには、作成した要素をどこかの親要素に追加する必要があります。また、要素を削除する場合も、親要素から子要素を取り除くという考え方になります。DOM操作では、どの要素の中に何を入れるのかを意識することが大切です。

3.3 要素・テキスト・属性

DOMには、要素、テキスト、属性という基本的な構成要素があります。要素はHTMLタグに対応し、テキストは要素の中に表示される文字列に対応し、属性はclass、id、src、href、altなどの情報に対応します。JavaScriptでは、これらを個別に取得・変更できます。

たとえば、画像のsrc属性を変更すれば表示される画像を変えられます。リンクのhref属性を変更すれば遷移先を変えられます。ボタンのテキストを変更すれば画面上の表示が変わります。このように、要素・テキスト・属性を理解することで、DOM操作の基本が見えてきます。

4. JavaScriptとDOMの関係

JavaScriptとDOMの関係は、Webページを動的に操作するための中心的な関係です。JavaScriptはプログラミング言語であり、DOMはブラウザが提供する文書操作の仕組みです。JavaScriptからDOM APIを呼び出すことで、Webページ上の要素を取得したり変更したりできます。

重要なのは、DOMはJavaScriptそのものではなく、ブラウザが提供するAPIであるという点です。JavaScriptの標準機能だけではHTML要素を操作できません。ブラウザ環境ではdocumentやwindowなどのオブジェクトが提供され、それらを通じてDOMを扱えるようになります。

4.1 ブラウザAPIとしてのDOM

DOMはブラウザAPIの一部です。ブラウザはHTMLを読み込み、DOMツリーを構築し、JavaScriptから操作できるようにします。documentオブジェクトはその代表であり、ページ全体のDOMにアクセスする入口になります。

たとえば、document.getElementById()document.querySelector()は、ブラウザが提供するDOM APIです。これらを使うことで、JavaScriptから特定のHTML要素を取得できます。DOM APIを理解することは、フロントエンド開発の基本です。

4.2 JavaScriptからのアクセス

JavaScriptからDOMへアクセスするには、まず対象となる要素を取得します。id、class、タグ名、CSSセレクタなどを使って要素を取得し、その後にプロパティやメソッドを使って内容や属性を変更します。これがDOM操作の基本的な流れです。

たとえば、ボタン要素を取得してクリックイベントを設定し、クリックされたらテキストを変更する処理は、DOM操作とイベント処理を組み合わせた典型的な例です。JavaScriptはDOMを通じて、ユーザー操作に応じた画面変化を実現します。

4.3 動的操作の仕組み

DOMを変更すると、ブラウザはその変更を画面に反映します。たとえば、要素のテキストを変更すると表示文字が変わり、新しい要素を追加すると画面上に表示されます。このように、DOMは画面表示と密接に関係しています。

ただし、DOMを変更するたびにブラウザは再計算や再描画を行う場合があります。大量のDOM操作を頻繁に行うと、パフォーマンスが低下することがあります。動的操作を実装する際は、必要な変更だけを効率よく行うことが重要です。

5. DOM操作の基本

DOM操作の基本は、要素を取得し、内容を変更し、属性やスタイルを変更することです。まずJavaScriptで目的の要素を見つけ、その要素に対して操作を行います。要素を取得できなければ、テキストや属性を変更することはできません。

DOM操作は小さな処理から始めると理解しやすいです。たとえば、見出しの文字を変える、ボタンの色を変える、画像のURLを変更する、といった処理です。これらの基本操作を組み合わせることで、複雑なUIも実装できるようになります。

5.1 要素の取得

要素の取得は、DOM操作の最初のステップです。JavaScriptでは、getElementByIdquerySelectorquerySelectorAllなどを使ってHTML要素を取得します。取得した要素はオブジェクトとして扱われ、そのプロパティやメソッドを使って操作できます。

要素取得では、対象が存在しない場合も考慮する必要があります。存在しないセレクタを指定するとnullが返ることがあるため、そのまま操作するとエラーになります。実務では、要素が取得できたかを確認してから操作することが重要です。

5.2 内容の変更

要素を取得したら、その内容を変更できます。テキストを変更するには、innerTexttextContentを使います。HTML構造ごと変更したい場合はinnerHTMLを使うこともありますが、セキュリティ上の注意が必要です。

内容の変更は、画面表示を動的に変える基本操作です。たとえば、フォームの入力内容に応じてメッセージを表示したり、APIから取得したデータを一覧として表示したりできます。ユーザーに現在の状態を伝えるためにも重要な操作です。

5.3 属性の変更

DOM操作では、要素の属性も変更できます。画像のsrc、リンクのhref、入力欄のplaceholder、ボタンのdisabledなどをJavaScriptから操作できます。属性を変更することで、要素の動作や表示内容を動的に切り替えられます。

たとえば、フォームの入力が不正な場合に送信ボタンをdisabledにする、画像ギャラリーで表示画像を切り替える、リンク先を条件に応じて変更する、といった処理が可能です。属性操作は、UIの状態管理でよく使われます。

6. 要素の取得方法

DOM操作では、目的の要素を正確に取得することが重要です。要素の取得方法にはいくつかの種類があり、idで取得する方法、CSSセレクタで取得する方法、複数要素をまとめて取得する方法などがあります。用途に応じて適切なメソッドを使い分ける必要があります。

現在の実務では、querySelectorquerySelectorAllがよく使われます。CSSセレクタと同じ感覚で要素を指定できるため、柔軟で分かりやすいからです。一方、idが明確な要素を取得する場合はgetElementByIdもシンプルで高速です。

6.1 getElementById

getElementByIdは、指定したidを持つ要素を取得するメソッドです。idはHTML文書内で一意であることが前提のため、特定の要素を直接取得したい場合に向いています。フォーム、ボタン、特定の表示領域など、明確に一つの要素を操作したいときに便利です。

ただし、idに依存しすぎると、HTML構造や命名の変更に弱くなる場合があります。実務では、JavaScriptから操作する目的でidを付ける場合もありますが、コンポーネント設計や再利用性を考えると、classやdata属性を使うこともあります。

6.2 querySelector

querySelectorは、CSSセレクタを使って最初に一致した要素を取得するメソッドです。id、class、タグ名、属性セレクタ、子孫セレクタなど、CSSと同じような指定ができるため非常に柔軟です。現在のDOM操作では、よく使われる基本メソッドの一つです。

querySelectorは最初の一件だけを返すため、複数の要素をまとめて操作したい場合には向いていません。単一のボタンや特定のコンテナを取得する場合に使いやすいメソッドです。セレクタが複雑になりすぎると保守性が下がるため、分かりやすい指定を心がけることが重要です。

6.3 querySelectorAll

querySelectorAllは、CSSセレクタに一致するすべての要素を取得するメソッドです。戻り値はNodeListであり、複数の要素に対してループ処理を行いたい場合に使います。たとえば、すべてのボタンにイベントを設定する、複数のカード要素にクラスを追加する、といった処理で利用されます。

querySelectorAllで取得した要素群は配列に似ていますが、通常の配列とは異なる点があります。ただし、forEachを使って処理できる環境が多いため、実務では比較的扱いやすいです。複数要素を操作する場合は、処理回数やパフォーマンスにも注意が必要です。

7. 要素の内容変更

要素の内容変更は、DOM操作の中でも非常によく使われる処理です。画面に表示するテキストを変更したり、HTML構造を挿入したり、APIから取得したデータを表示したりする際に利用します。代表的なプロパティには、innerTextinnerHTMLtextContentがあります。

これらは似ていますが、用途や挙動が異なります。単にテキストを表示したい場合はtextContentinnerTextを使うことが多く、HTMLタグを含む内容を挿入したい場合はinnerHTMLを使います。ただし、innerHTMLはセキュリティリスクを伴うため注意が必要です。

7.1 innerText

innerTextは、要素内の表示されているテキストを取得・変更するためのプロパティです。ブラウザ上で実際に見えているテキストに近い内容を扱います。CSSによって非表示になっている要素の扱いなど、表示状態を考慮する点が特徴です。

画面に表示するメッセージを変更する場合、innerTextは直感的に使えます。たとえば、ボタンをクリックした後に「送信しました」と表示する、エラー時に「入力内容を確認してください」と表示する、といった処理に利用できます。ただし、表示状態を考慮するため、単純なテキスト処理ではtextContentが選ばれることもあります。

7.2 innerHTML

innerHTMLは、要素内のHTMLを取得・変更するためのプロパティです。文字列としてHTMLタグを挿入できるため、複数の要素をまとめて生成したい場合に便利です。たとえば、APIから取得したデータをリスト形式のHTMLとして挿入することができます。

ただし、innerHTMLにはセキュリティ上の注意があります。ユーザー入力をそのままinnerHTMLに挿入すると、悪意あるスクリプトが実行されるクロスサイトスクリプティングの原因になる可能性があります。信頼できないデータを扱う場合は、textContentを使うか、適切にエスケープする必要があります。

7.3 textContent

textContentは、要素内のテキストを取得・変更するためのプロパティです。HTMLタグを解釈せず、純粋なテキストとして扱います。そのため、ユーザー入力や外部データを安全に表示したい場合に適しています。

textContentは、表示状態に左右されにくく、処理も比較的シンプルです。単純に文字列を表示するだけであれば、innerHTMLよりも安全で分かりやすい選択肢になります。実務では、HTMLを挿入する必要がない限り、textContentを優先することが多いです。

8. 属性の操作

属性の操作は、DOM要素の振る舞いや表示内容を変更するために使います。HTML要素には、id、class、src、href、alt、disabled、checked、data属性など、さまざまな属性があります。JavaScriptからこれらを取得・変更・削除することで、UIの状態を動的に制御できます。

属性操作は、画像切り替え、リンク変更、フォーム制御、アクセシビリティ対応、状態管理などでよく使われます。特に、data属性を使うと、HTML要素にJavaScript用の情報を持たせることができ、イベント処理やコンポーネント制御で便利です。

8.1 setAttribute

setAttributeは、指定した属性に値を設定するメソッドです。たとえば、画像要素のsrcを変更したり、リンク要素のhrefを変更したり、ボタンにdisabled属性を付与したりできます。属性が存在しない場合は新しく追加され、存在する場合は値が上書きされます。

setAttributeは汎用的に使えるため便利ですが、プロパティとして直接操作できる属性もあります。たとえば、inputのvalueやbuttonのdisabledは、要素のプロパティとして扱うこともできます。実務では、属性とプロパティの違いを意識しながら使うことが重要です。

8.2 getAttribute

getAttributeは、指定した属性の値を取得するメソッドです。要素に設定されているhref、src、data属性などを取得したい場合に利用します。特に、HTML上に書かれたdata属性をJavaScriptで読み取る処理でよく使われます。

属性値を取得することで、要素ごとの設定や状態をJavaScript側で判断できます。たとえば、ボタンにdata-idを持たせておき、クリックされたときにどのデータを操作するか判断する、といった使い方ができます。HTMLとJavaScriptを連携させるうえで便利な機能です。

8.3 removeAttribute

removeAttributeは、指定した属性を削除するメソッドです。たとえば、ボタンのdisabled属性を削除して再び押せるようにする、フォームのreadonlyを解除する、不要になったaria属性を取り除くといった処理に使えます。

属性の削除は、UIの状態切り替えでよく使われます。ただし、属性を削除することが適切か、値を変更するだけでよいかは状況によって異なります。フォームやアクセシビリティに関係する属性では、動作への影響を確認しながら操作することが重要です。

9. スタイルの変更

DOM操作では、要素のスタイルをJavaScriptから変更できます。代表的な方法には、styleプロパティを直接変更する方法、classListでCSSクラスを追加・削除する方法、CSSと連携して状態を表現する方法があります。実務では、直接styleを変更するよりも、classListを使ってCSSクラスを切り替える方法がよく使われます。

スタイル変更は、UIの状態を表現するために重要です。エラー時に赤枠を表示する、開閉状態に応じてメニューを表示する、選択中のタブにアクティブクラスを付ける、スクロールに応じてヘッダーの見た目を変えるなど、多くの場面で使われます。

9.1 styleプロパティ

styleプロパティを使うと、JavaScriptから直接インラインスタイルを設定できます。たとえば、element.style.colorelement.style.displayのように指定します。特定の要素に対して一時的にスタイルを変更したい場合には便利です。

ただし、styleプロパティを多用すると、CSSとJavaScriptの責務が混ざりやすくなります。スタイルの定義がCSSではなくJavaScript内に散らばると、保守性が低下することがあります。基本的には、状態の切り替えはCSSクラスで管理し、styleプロパティは限定的に使うのが望ましいです。

9.2 classList操作

classListは、要素のCSSクラスを操作するための便利なAPIです。addでクラスを追加し、removeで削除し、toggleで付け外しを切り替え、containsでクラスの有無を確認できます。UIの状態管理では非常によく使われます。

classListを使うと、スタイル定義はCSS側に置き、JavaScriptは状態に応じてクラスを切り替えるだけで済みます。たとえば、モーダルを開くときにis-openクラスを追加し、閉じるときに削除するような実装です。この分離により、保守性が高くなります。

9.3 CSSとの連携

DOM操作とCSSを連携させることで、見た目の変更を整理しやすくなります。JavaScriptは状態を判断してクラスを付け替え、CSSはそのクラスに応じた見た目を定義します。この役割分担により、スタイル変更の管理がしやすくなります。

たとえば、.is-active.is-hidden.is-disabled.has-errorのような状態クラスを用意しておくと、JavaScript側ではクラスを切り替えるだけでUIを制御できます。実務では、このように状態をクラス名で表現する設計がよく使われます。

10. 要素の追加と削除

DOM操作では、新しい要素を作成して画面に追加したり、不要になった要素を削除したりできます。これにより、リストを動的に生成する、通知メッセージを表示する、フォーム項目を追加する、モーダルを生成するなどの処理が可能になります。

要素の追加と削除は、動的なWebアプリケーションに欠かせない操作です。ただし、大量の要素を一つずつ追加・削除するとパフォーマンスに影響することがあります。実務では、DocumentFragmentやテンプレート、フレームワークのレンダリング機能を使って効率化することもあります。

10.1 createElement

createElementは、新しいHTML要素を作成するメソッドです。たとえば、document.createElement('li')とすると、新しいli要素を作成できます。ただし、この時点では画面には表示されません。作成した要素をDOMツリーのどこかに追加することで、初めて画面に反映されます。

作成した要素には、テキストを設定したり、クラスを追加したり、属性を設定したりできます。APIから取得したデータをもとにカードやリスト項目を作成する場合など、動的なUI生成でよく使われます。

10.2 appendChild

appendChildは、指定した親要素の末尾に子要素を追加するメソッドです。createElementで作成した要素を画面に表示するには、親要素に対してappendChildを実行します。これにより、DOMツリーに新しい要素が追加されます。

たとえば、ul要素にli要素を追加すれば、リスト項目が画面に表示されます。appendChildは基本的なDOM追加操作ですが、現在ではappendinsertAdjacentHTMLなど他の方法も使われます。用途に応じて使い分けることが重要です。

10.3 removeChild

removeChildは、親要素から指定した子要素を削除するメソッドです。不要になったメッセージ、リスト項目、モーダル、エラー表示などをDOMから取り除く場合に利用します。削除された要素は画面からも消えます。

現在では、要素自身に対してremove()を使う方法も一般的です。ただし、DOMの親子関係を理解するうえでは、removeChildの考え方は重要です。どの親要素からどの子要素を削除するのかを意識することで、DOM操作の構造を理解しやすくなります。

11. イベントとDOM操作

イベントとDOM操作は密接に関係しています。ユーザーがボタンをクリックする、フォームに文字を入力する、マウスを動かす、スクロールする、キーを押すといった操作はイベントとして扱われます。JavaScriptはイベントを検知し、そのタイミングでDOMを操作できます。

イベント処理を使うことで、ユーザー操作に応じたインタラクティブなUIを作れます。クリックされたらメニューを開く、入力されたら文字数を表示する、フォーム送信前にバリデーションする、スクロールに応じてヘッダーを固定する、といった処理が代表例です。

11.1 clickイベント

clickイベントは、ユーザーが要素をクリックしたときに発生するイベントです。ボタン、リンク、メニュー、カード、アイコンなど、さまざまなUI要素で利用されます。clickイベントに処理を登録することで、クリック時にDOMを変更できます。

たとえば、ボタンをクリックしたらテキストを変更する、モーダルを表示する、メニューを開閉する、選択中の項目を切り替えるといった処理が実装できます。clickイベントはDOM操作を学ぶうえで最も基本的なイベントの一つです。

11.2 inputイベント

inputイベントは、入力欄の値が変更されたときに発生するイベントです。テキスト入力、検索フォーム、パスワード入力、textareaなどでよく使われます。ユーザーが入力するたびに処理を実行できるため、リアルタイムバリデーションや文字数カウントに適しています。

たとえば、フォームに入力された文字数を表示する、入力内容をプレビューに反映する、検索候補を表示する、といった処理が可能です。ただし、inputイベントは頻繁に発生するため、重い処理を実行する場合はdebounceなどで制御することも重要です。

11.3 addEventListener

addEventListenerは、要素にイベント処理を登録するためのメソッドです。click、input、change、submit、keydownなど、さまざまなイベントに対して処理を設定できます。現代のJavaScriptでは、イベント登録の基本的な方法として広く使われています。

addEventListenerを使うことで、HTMLとJavaScriptを分離しやすくなります。HTML属性に直接onclickを書く方法もありますが、実務ではJavaScript側でイベントを登録する方が保守しやすい場合が多いです。複数のイベント処理を整理して管理するうえでも重要なAPIです。

12. DOM操作の例

DOM操作は、実際のUIでさまざまな形で利用されます。ボタンを押してテキストを変更する、フォーム入力を処理する、データをもとにリストを生成するなどは、基本的でありながら実務でも頻繁に使われる処理です。これらを理解すると、DOM操作の全体像が見えやすくなります。

DOM操作の例では、要素取得、イベント登録、内容変更、要素追加などの基本処理が組み合わさります。小さな操作を積み重ねることで、タブ切り替え、アコーディオン、モーダル、検索UI、動的フォームなど、複雑なインタラクションも実装できます。

12.1 ボタンでテキスト変更

ボタンでテキストを変更する処理は、DOM操作の最も基本的な例です。まずボタン要素と表示対象のテキスト要素を取得し、ボタンにclickイベントを登録します。クリックされたら、テキスト要素のtextContentinnerTextを変更します。

この例では、要素取得、イベント処理、内容変更というDOM操作の基本が含まれています。非常にシンプルですが、ユーザー操作に応じて画面が変わる仕組みを理解するうえで重要です。多くのUI処理は、この基本パターンを発展させたものです。

12.2 フォーム入力処理

フォーム入力処理では、inputイベントやsubmitイベントを使ってDOMを操作します。たとえば、ユーザーが入力した文字数を表示したり、入力内容が条件を満たしていない場合にエラーメッセージを表示したりできます。フォームバリデーションでもDOM操作はよく使われます。

フォーム処理では、入力値の取得、エラー表示、ボタンの有効・無効切り替え、入力欄のスタイル変更などが発生します。これらを適切に組み合わせることで、ユーザーに分かりやすいフォームUIを作ることができます。

12.3 動的リスト生成

動的リスト生成は、APIや配列データをもとにDOM要素を作成し、画面に表示する処理です。たとえば、商品一覧、記事一覧、コメント一覧、検索結果などをJavaScriptで生成する場合に使われます。createElementappendChild、またはテンプレート文字列を使って要素を作成します。

大量のデータを表示する場合は、パフォーマンスに注意が必要です。一つずつDOMに追加すると再描画が多くなる場合があるため、まとめて追加する工夫が必要になります。現代のフレームワークでは、このようなリスト生成を宣言的に扱えるようになっています。

13. DOM操作の問題点

DOM操作は便利ですが、使い方を誤ると問題も発生します。代表的な問題は、パフォーマンス低下、コードの複雑化、再レンダリングコストです。特に、大量の要素を頻繁に更新する場合や、DOM操作が複数箇所に散らばっている場合、保守性が下がりやすくなります。

DOMはブラウザの表示と密接に関係しているため、変更にはコストがかかります。要素の追加、削除、サイズ変更、スタイル変更などが発生すると、ブラウザはレイアウト計算や描画を行う場合があります。そのため、DOM操作は必要最小限に抑え、効率的に行うことが重要です。

13.1 パフォーマンス低下

DOM操作によるパフォーマンス低下は、頻繁な更新や大量の要素操作によって発生します。たとえば、ループの中で何度もDOMに要素を追加すると、そのたびにブラウザがレイアウトや描画を行う可能性があります。これが積み重なると、画面が重くなります。

パフォーマンスを改善するには、DOM操作をまとめる、DocumentFragmentを使う、不要な再計算を避ける、表示に必要な要素だけを更新するなどの工夫が必要です。特に大量データを扱う場合は、仮想スクロールやフレームワークの最適化機能も検討されます。

13.2 コードの複雑化

DOM操作を直接書きすぎると、コードが複雑になりやすいです。要素取得、状態管理、イベント処理、表示更新が同じファイルに混在すると、どの操作がどの画面変化につながっているのか分かりにくくなります。特にUIが複雑になるほど、この問題は大きくなります。

コードの複雑化を防ぐには、関数分割、状態管理、イベントの整理、HTML構造とJavaScriptの責務分離が重要です。また、複雑なUIではReactやVueのようなフレームワークを使い、DOM操作を宣言的に扱う方が保守しやすい場合があります。

13.3 再レンダリングコスト

DOMを変更すると、ブラウザは画面表示を更新します。このとき、レイアウト再計算や再描画が発生する場合があります。特に、要素のサイズや位置に関わる変更はコストが高くなることがあります。再レンダリングが頻繁に起こると、ユーザー操作が重く感じられます。

再レンダリングコストを抑えるには、DOMの読み取りと書き込みを整理することが重要です。何度もサイズを読み取りながらスタイルを書き換えるような処理は避け、必要な情報をまとめて取得し、変更もまとめて行うと効率的です。

14. 仮想DOMとの違い

仮想DOMとは、実際のDOMを直接操作するのではなく、JavaScript上に軽量なDOMのような構造を作り、差分を計算して必要な部分だけ実際のDOMへ反映する仕組みです。Reactなどで使われる考え方として知られています。仮想DOMは、DOM操作を効率化し、UI更新を管理しやすくするために利用されます。

ただし、仮想DOMは魔法のように常に高速というわけではありません。重要なのは、UIを状態に基づいて宣言的に記述し、実際のDOM更新をライブラリに任せられる点です。直接DOM操作と仮想DOMの違いを理解すると、現代フロントエンドの仕組みが分かりやすくなります。

14.1 ReactのVirtual DOM

Reactでは、状態が変化すると仮想DOMを再構築し、前回の仮想DOMとの差分を計算します。その差分をもとに、必要な部分だけ実際のDOMへ反映します。この仕組みにより、開発者は直接DOMを操作するのではなく、状態に応じたUIを宣言的に書けます。

Reactの開発では、通常document.querySelectorで要素を取得して直接変更するのではなく、stateを変更してUIを更新します。これにより、DOM操作がコードのあちこちに散らばることを防ぎ、UIの状態を管理しやすくなります。

14.2 差分更新

差分更新とは、変更前と変更後を比較し、必要な部分だけ更新する仕組みです。仮想DOMでは、JavaScript上の仮想的なツリーを比較して、実際のDOMへの反映を最小限に抑えます。これにより、手動でDOM更新を細かく管理する負担が減ります。

ただし、差分更新にもコストはあります。非常に大規模なUIや頻繁な更新では、適切なコンポーネント分割やメモ化が必要になることもあります。仮想DOMを使っていても、パフォーマンスを意識した設計は重要です。

14.3 効率化の仕組み

仮想DOMによる効率化の本質は、DOM操作を直接大量に行うのではなく、状態の変化から必要な更新を整理して反映することです。開発者は「この状態ならこのUIを表示する」と記述し、実際の更新手順はフレームワークが管理します。

これにより、UIが複雑になってもコードを整理しやすくなります。直接DOM操作では、どのイベントでどの要素をどう変更するかを細かく書く必要がありますが、仮想DOMを使うフレームワークでは、状態と表示の対応関係を中心に考えられます。

15. フレームワークとの関係

React、Vue、Angularなどのフロントエンドフレームワークは、DOM操作を効率化し、複雑なUIを管理しやすくするために利用されます。これらのフレームワークでは、開発者が直接DOMを操作する場面は少なくなり、状態やデータに基づいてUIを宣言的に記述します。

ただし、フレームワークを使う場合でも、DOMの理解は重要です。イベント、レンダリング、コンポーネントの更新、ref、ライフサイクル、アクセシビリティなど、多くの概念がDOMと関係しています。DOM操作の基礎を理解していると、フレームワークの挙動も理解しやすくなります。

15.1 React

Reactでは、UIをコンポーネントとして構築し、stateやpropsに応じて表示を更新します。開発者が直接DOMを変更するのではなく、状態を変更するとReactが必要なDOM更新を行います。これにより、UIの状態管理が整理しやすくなります。

ただし、フォームのフォーカス制御や外部ライブラリ連携など、一部では実際のDOM要素にアクセスする必要があります。その場合はrefを使います。ReactでもDOMの存在は消えるわけではなく、直接操作を最小限にしながら必要な場面で扱うという考え方になります。

15.2 Vue

Vueも、データに基づいてDOMを更新するフレームワークです。テンプレート構文を使い、データが変化すると対応するUIが自動的に更新されます。開発者は、DOMを直接変更するよりも、データや状態を変更することで画面を更新します。

Vueでは、条件分岐やリスト表示、イベント処理をテンプレート内で分かりやすく記述できます。DOM操作を抽象化することで、複雑なUIでもコードを整理しやすくなります。ただし、Vueでも実際の表示はDOMによって行われるため、DOMの基本理解は役立ちます。

15.3 Angular

Angularは、大規模アプリケーション向けのフレームワークであり、コンポーネント、テンプレート、データバインディング、依存性注入などを備えています。Angularでも、開発者は直接DOMを操作するより、テンプレートとデータバインディングを通じてUIを更新します。

Angularでは、DOM操作を直接行うよりも、フレームワークの仕組みに沿って実装することが推奨されます。直接DOMへ依存しすぎると、テストや保守が難しくなることがあります。フレームワークを使う場合は、その設計思想に従ってDOM更新を管理することが重要です。

16. DOM操作のベストプラクティス

DOM操作を実務で使う際には、直接操作を最小化し、更新をまとめ、イベント委譲を活用することが重要です。DOM操作は便利ですが、無計画に使うとパフォーマンスや保守性に問題が出ます。特に、複雑なUIでは状態管理とDOM更新の責務を整理する必要があります。

また、JavaScriptとCSSの役割分担も大切です。JavaScriptで細かいスタイルを直接書くのではなく、CSSクラスを切り替えて見た目を変える方が保守しやすいです。DOM操作では、何をJavaScriptで制御し、何をCSSで表現するかを意識することが重要です。

16.1 直接操作の最小化

直接DOM操作は、必要な箇所に限定するべきです。すべてのUI変更を個別のDOM操作として書くと、状態管理が複雑になり、コードが読みにくくなります。可能であれば、状態を一箇所で管理し、その状態に応じてUIを更新する設計が望ましいです。

特にReactやVueなどのフレームワークを使っている場合、直接DOM操作は最小限にするべきです。フレームワークが管理するDOMを外部から直接変更すると、状態と画面の整合性が崩れることがあります。直接操作が必要な場合も、フレームワークの推奨方法に従うことが重要です。

16.2 バッチ更新

DOM更新は、できるだけまとめて行うことが望ましいです。複数の要素を一つずつ追加したり、何度もスタイルを書き換えたりすると、ブラウザの再計算や再描画が増える可能性があります。更新をまとめることで、パフォーマンスを改善できます。

たとえば、大量のリスト項目を追加する場合は、DocumentFragmentを使って一時的にまとめてからDOMに追加する方法があります。また、HTML文字列をまとめて生成して一度に挿入する方法もあります。ただし、innerHTMLを使う場合はセキュリティに注意が必要です。

16.3 イベント委譲

イベント委譲とは、複数の子要素にそれぞれイベントを設定するのではなく、親要素にイベントを設定して、イベントの発生元を判定する方法です。DOMのイベントは親要素へ伝播するため、この仕組みを利用できます。

イベント委譲を使うと、大量の要素に個別のイベントリスナーを設定する必要がなくなります。また、後から動的に追加された要素にも対応しやすくなります。リスト、テーブル、メニュー、カード一覧など、多数の要素を扱うUIで有効です。

17. 実務での活用例

DOM操作は、実務のフロントエンド開発で幅広く使われます。SPA開発、フォームバリデーション、UIインタラクション、管理画面、検索UI、モーダル、タブ、アコーディオン、通知表示など、多くの機能がDOM操作と関係しています。フレームワークを使う場合でも、DOMの考え方は基礎として重要です。

実務では、DOM操作を直接書く場面と、フレームワークに任せる場面を使い分けることが重要です。小さな静的サイトでは直接DOM操作で十分な場合がありますが、複雑なWebアプリケーションではReactやVueなどを使って状態管理とDOM更新を整理する方が適していることがあります。

17.1 SPA開発

SPAは、Single Page Applicationの略で、ページ全体を再読み込みせずに画面を切り替えるWebアプリケーションの形式です。SPAでは、JavaScriptが画面表示を管理し、必要なデータをAPIから取得してDOMに反映します。ReactやVueなどのフレームワークがよく使われます。

SPAでは、状態の変化に応じてDOMを効率よく更新することが重要です。直接DOM操作だけで大規模なSPAを作ると、状態管理が複雑になりやすいため、フレームワークによる抽象化が有効です。それでも、最終的に画面がDOMとして描画されることを理解しておく必要があります。

17.2 フォームバリデーション

フォームバリデーションでは、DOM操作がよく使われます。入力値を確認し、エラーがある場合はメッセージを表示したり、入力欄にエラー用のクラスを追加したり、送信ボタンを無効化したりします。ユーザーに分かりやすくエラーを伝えるために、DOM操作は重要です。

実務では、HTML標準のバリデーション、JavaScriptによるカスタムバリデーション、フレームワークのフォームライブラリなどを組み合わせます。いずれの場合も、エラー表示や状態変更はDOMに反映されるため、DOMの基本理解が役立ちます。

17.3 UIインタラクション

UIインタラクションとは、ユーザー操作に応じて画面が変化する仕組みです。タブ切り替え、アコーディオン、ドロップダウンメニュー、モーダル、ツールチップ、スライダー、通知表示などが代表例です。これらはDOM操作とイベント処理によって実現されます。

UIインタラクションを実装する際は、見た目だけでなくアクセシビリティも考慮する必要があります。たとえば、モーダルではフォーカス管理やaria属性、キーボード操作への対応が重要です。DOM操作は、視覚的な変化だけでなく、ユーザーが正しく操作できる状態を作るためにも使われます。

おわりに

DOM操作は、JavaScriptからHTML構造を動的に変更する仕組みです。ブラウザがHTMLを読み込むとDOMツリーが構築され、JavaScriptはそのDOMにアクセスして、要素の取得、内容変更、属性変更、スタイル変更、要素の追加・削除、イベント処理などを行えます。これにより、Webページはユーザー操作に応じて変化するインタラクティブな画面になります。

DOMは、Document Object Modelの略で、HTML文書をオブジェクトのツリー構造として表現したものです。HTMLのタグ、テキスト、属性はDOM上のノードとして扱われます。DOMツリーの親子関係やノードの概念を理解すると、JavaScriptでどのように画面を操作できるのかが分かりやすくなります。

DOM操作には、要素取得、テキスト変更、属性操作、classListによるスタイル切り替え、createElementによる要素作成、addEventListenerによるイベント処理など、多くの基本技術があります。これらは、フォームバリデーション、動的リスト生成、モーダル、タブ、メニューなど、実務のUI開発で頻繁に使われます。

一方で、DOM操作を過剰に行うと、パフォーマンス低下やコードの複雑化につながることがあります。大量のDOM更新、深い依存関係、散らばったイベント処理は保守性を下げる原因になります。そのため、直接操作を最小化し、更新をまとめ、イベント委譲を活用することが重要です。

React、Vue、Angularなどのフレームワークは、DOM操作を効率化し、複雑なUIを管理しやすくするために利用されます。これらのフレームワークを使う場合でも、DOMの仕組みを理解しておくことは重要です。DOM操作は、現代フロントエンド開発を理解するための基礎概念であり、Webアプリケーションのインタラクティブ性を支える重要な技術です。

LINE Chat