DOMとは — ドキュメントオブジェクトモデル
このトピックを終えると
DOMが何であるかを説明でき、JavaScriptを使用してHTML要素を選択、コンテンツを変更、イベントをアタッチする基本的な操作ができるようになります。
HTMLはテキスト、DOMはオブジェクト
ブラウザがHTMLファイルを受け取ると、テキストをそのまま画面に描画するわけではありません。HTMLテキストをパースして、メモリ上にツリー構造のオブジェクトを作成します。このオブジェクトツリーがDOM(Document Object Model)です。
<html>
<body>
<h1>こんにちは</h1>
<p> 반갑습니다</p>
</body>
</html>document
└── html
└── body
├── h1 → "こんにちは"
└── p → " 반갑습니다"すべてのHTMLタグ、テキスト、属性が、このツリーのノードになります。JavaScriptはこのツリーを通じてHTMLを読み、修正、削除できます。
要素の選択
DOMを操作するには、まず目的の要素を選択する必要があります。
// IDで選択(1つだけ返却)
const title = document.getElementById('main-title');
// CSSセレクターで選択(最初の1つ)
const firstCard = document.querySelector('.card');
// CSSセレクターで選択(すべて)
const allCards = document.querySelectorAll('.card');querySelectorはCSSセレクターをそのまま使用できるため、最も汎用的です。クラスは.card、IDは#main-title、タグはpで選択します。
// 組み合わせも可能
const activeItem = document.querySelector('ul.menu > li.active');コンテンツの読み込みと修正
const heading = document.querySelector('h1');
// 読み込み
console.log(heading.textContent); // "こんにちは"
console.log(heading.innerHTML); // "こんにちは" (HTMLタグを含む)
// 修正
heading.textContent = 'ようこそ'; // テキストのみ変更
heading.innerHTML = '<em>ようこそ</em>'; // HTMLの挿入が可能textContentは純粋なテキスト、innerHTMLはHTMLマークアップを扱います。ユーザー入力をinnerHTMLに入れると、XSS攻撃に脆弱になるため、ユーザーデータはtextContentを使用します。
スタイルと属性の変更
const box = document.querySelector('.box');
// インラインスタイルを変更
box.style.backgroundColor = '#3498db';
box.style.padding = '20px';
// CSSクラスの操作(推奨)
box.classList.add('active');
box.classList.remove('hidden');
box.classList.toggle('selected');インラインスタイルを直接変更することもできますが、CSSクラスを追加/削除する方が保守性に優れています。スタイルはCSSファイルに、動作はJavaScriptに分離するという原則です。
// 属性の変更
const img = document.querySelector('img');
img.setAttribute('src', 'new-image.png');
img.setAttribute('alt', '新しい画像');
// data属性
const card = document.querySelector('[data-id="42"]');
console.log(card.dataset.id); // "42"要素の作成と追加
// 新しい要素を作成
const newItem = document.createElement('li');
newItem.textContent = '新しい項目';
newItem.classList.add('item');
// 既存の要素に追加
const list = document.querySelector('ul');
list.appendChild(newItem); // 最後に追加
list.prepend(newItem); // 最初に追加
list.insertBefore(newItem, list.children[1]); // 特定の位置に挿入// 複数の要素を一度に追加する場合
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `項目 ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // DOMへのアクセスを1回にDocumentFragmentを使用すると、反復的なDOMの修正をまとめて1回で処理できます。DOMへのアクセスはコストの高い操作なので、回数を減らすことがパフォーマンス向上につながります。
イベント — ユーザーの操作に反応する
const button = document.querySelector('#submit');
button.addEventListener('click', function(event) {
console.log('ボタンがクリックされました');
console.log(event.target); // クリックされた要素
});addEventListenerは3つの部分で構成されます。
- イベント名:
'click'、'input'、'submit'、'keydown'など - コールバック関数: イベントが発生すると実行される関数
eventオブジェクト: イベントに関する情報(どのキーが押されたか、マウスの座標など)
// 入力フィールドのリアルタイム反応
const input = document.querySelector('#search');
input.addEventListener('input', function(e) {
console.log('現在の入力:', e.target.value);
});イベント委譲
ボタン100個にそれぞれイベントを付ける代わりに、親要素に1つだけ付けることができます。
// ❌ 非効率 — 100個のリスナー
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// ✅ イベント委譲 — 1つのリスナー
document.querySelector('#list').addEventListener('click', function(e) {
if (e.target.classList.contains('item')) {
console.log('クリックされた項目:', e.target.textContent);
}
});クリックイベントは、子要素から親要素へバブルアップ(bubbling)します。親要素でe.targetを確認することで、実際にクリックされた子要素を特定できます。動的に追加される要素にも自動的に適用されるという利点があります。
textContent vs innerHTML のセキュリティ
const userInput = '<script>alert("ハッキング")</script>';
element.innerHTML = userInput; // ❌ 危険 — XSS攻撃の可能性
element.textContent = userInput; // ✅ 安全 — タグがテキストとして表示されるユーザー入力をinnerHTMLに入れると、悪意のあるスクリプトが実行される可能性があります。ユーザー入力には必ずtextContentを使用してください。HTML構造を動的に作成する必要がある場合は、createElementで組み立てるのが安全です。
DOMとフレームワーク
現代のフロントエンドフレームワーク(React、Vue、Svelte)を使用すると、DOMを直接操作する必要はありません。フレームワークが仮想DOM(Virtual DOM)またはコンパイラを通じて代わりに処理します。
直接DOM操作:
開発者 → querySelector → DOMを直接修正
React方式:
開発者 → stateの変更 → ReactがDOMを修正しかし、DOMの原理を理解していないと:
- フレームワークの動作を理解できません
- パフォーマンスの問題をデバッグできません
- フレームワークなしで迅速なプロトタイプを作成できません
主要なまとめ
| 操作 | メソッド |
|---|---|
| 選択 | querySelector()、querySelectorAll() |
| 読み込み/修正 | textContent、innerHTML |
| スタイル | classList.add/remove/toggle |
| 作成 | createElement()、appendChild() |
| イベント | addEventListener() |
| イベント委譲 | 親にリスナー + e.target の確認 |
DOMは、JavaScriptがWebページを動的に作成するための主要なインターフェースです。Reactなどのフレームワークを使用すると、DOMを直接操作する必要はなくなりますが、DOMがどのように機能するかを理解しておくと、デバッグと最適化に大きな役立ちます。