DOM API とは何か
DOM API は、ブラウザが作る「HTML の木構造(DOM ツリー)」を JavaScript から読み書きするための関数やプロパティ群です。document を起点にノード(要素・テキスト・コメント)を取得し、内容や属性を変更し、イベントを登録し、要素を作成・挿入・削除できます。ここが重要です:DOM は“画面そのもの”ではなく“設計図”。設計図(DOM)を変えると、ブラウザが画面を再描画します。
ノードとツリーの基本(document・要素・テキスト)
ツリーの構造を掴む
<h1 id="title">こんにちは</h1>
<p class="msg">DOM は木構造</p>
HTMLconst title = document.querySelector("#title"); // 要素ノード
console.log(title.parentNode === document.body); // true(親)
console.log(title.firstChild.nodeType); // 3(テキストノード)
JavaScriptDOM は親子・兄弟の関係を持つツリーです。要素の中の文字は「テキストノード」として別扱いになります。要素だけを辿るなら children/nextElementSibling、テキストも含めるなら childNodes/nextSibling を使い分けます。
要素の取得とコレクション(静的とライブの違いを深掘り)
代表的な取得 API
document.getElementById("title"); // 速い・一意
document.querySelector(".msg"); // CSS セレクタで柔軟に1件
document.querySelectorAll(".msg"); // すべて(NodeList)
document.getElementsByClassName("msg"); // ライブな HTMLCollection
JavaScript静的 NodeList と ライブ HTMLCollection
const staticList = document.querySelectorAll(".msg"); // 静的(後から増えても配列は固定)
const liveList = document.getElementsByClassName("msg"); // ライブ(DOM変化に同期)
const p = document.createElement("p");
p.className = "msg";
document.body.append(p);
console.log(staticList.length); // 元のまま
console.log(liveList.length); // 1 増える(ライブ)
JavaScriptここが重要です:処理の見通しが必要なら「静的」(querySelectorAll)、常に最新を反映したいなら「ライブ」(getElementsBy*)。ふだんは静的のほうがバグになりにくく扱いやすいです。
読み取り・更新の基本(textContent・innerHTML・属性・クラス)
テキストと HTML の違い
const el = document.querySelector("#title");
el.textContent = "<b>文字としてそのまま</b>"; // 安全(HTMLとしては解釈されない)
el.innerHTML = "<b>太字</b>"; // HTMLとして展開(安全性に注意)
JavaScriptここが重要です:外部データやユーザー入力は textContent が原則。innerHTML は信頼できる範囲に限定します(XSS対策)。
属性とプロパティ、classList と dataset
const btn = document.querySelector("#buy");
btn.setAttribute("aria-label", "購入"); // 属性の追加
btn.classList.add("is-active"); // クラス操作(CSS連携)
btn.dataset.sku = "SKU-123"; // data-* の読み書き(メタ情報)
JavaScriptここが重要です:表示と振る舞いはクラス(classList)で切り替え、JS が読む設定値は data-* に置くと、HTML/CSS/JS の責務分離が保てます。
ノードの作成・挿入・削除(組み立ての正攻法)
生成→設定→挿入
const li = document.createElement("li"); // 要素を作る
li.textContent = "項目"; // テキストを設定
document.querySelector("ul").append(li); // ツリーに追加
JavaScript便利な挿入 API(位置を選べる)
const box = document.querySelector("#box");
box.prepend(document.createTextNode("先頭に追加"));
box.append(document.createTextNode("末尾に追加"));
box.before(document.createElement("hr")); // 要素の前に
box.after(document.createElement("hr")); // 要素の後に
JavaScript置換・削除・大量追加
box.replaceWith(document.createElement("section")); // 置き換え
box.remove(); // 削除
const frag = document.createDocumentFragment(); // 大量追加はフラグメントで
for (let i = 0; i < 500; i++) {
const li = document.createElement("li");
li.textContent = `Item ${i}`;
frag.append(li);
}
document.querySelector("ul").append(frag);
JavaScriptここが重要です:生成→内容設定→まとめて挿入の順にすると、中途半端な描画を避け、再計算を減らせます。
イベントの基本(addEventListener と委譲)
要素に紐づける
document.addEventListener("DOMContentLoaded", () => {
const btn = document.querySelector("#buy");
btn.addEventListener("click", () => {
btn.classList.toggle("is-active");
});
});
JavaScript親で受ける“イベント委譲”
const list = document.querySelector(".tabs");
list.addEventListener("click", (e) => {
if (!(e.target instanceof HTMLButtonElement)) return;
const tab = e.target.dataset.tab;
document.querySelectorAll(".panel").forEach(p =>
p.classList.toggle("is-hidden", p.id !== `panel-${tab}`)
);
});
JavaScriptここが重要です:イベントは JS に集約(HTMLの onclick は避ける)。委譲を使うと、後から追加される要素にも処理を適用でき、登録数を減らせます。
トラバーサルと検索の応用(closest・matches)
近い祖先を探す
const btn = document.querySelector(".buy-button");
const card = btn.closest(".product-card"); // もっとも近い祖先
JavaScriptセレクタ適合判定
if (btn.matches(".buy-button.is-active")) {
// セレクタに合致するときの処理
}
JavaScriptここが重要です:closest は「今いる場所から安全に上へ辿る」ための武器。HTML 構造変更に強いフックが書けます。
パフォーマンスと安全性の勘所(読み書きのバッチ化・XSS)
読み取りと書き込みはまとめる
// 悪い例:読み書きが交互でレイアウト計算が何度も走る
const el = document.querySelector("#box");
const w = el.offsetWidth;
el.style.width = (w + 10) + "px";
const h = el.offsetHeight;
el.style.height = (h + 10) + "px";
// 良い例:読み取りをまとめ、書き込みをまとめる
const el2 = document.querySelector("#box2");
const w2 = el2.offsetWidth;
const h2 = el2.offsetHeight;
el2.style.width = (w2 + 10) + "px";
el2.style.height = (h2 + 10) + "px";
JavaScript安全な挿入の原則
- 外部データ・ユーザー入力は
textContentで入れる。 innerHTMLは限定・検証済みのテンプレートだけ。- クラス切り替えで見た目を制御してロジックを単純化。
ここが重要です:DOM 操作は強力だが重く、危険にもなり得ます。再描画コストを意識し、XSS を防ぎ、責務分離を徹底すると規模が大きくなっても安定します。
まとめ
DOM API は「要素を見つける」「読んで書く」「作って挿入・削除」「イベントを結びつける」「ツリーを辿る」という5つの柱で成り立っています。静的/ライブのコレクションを使い分け、textContent と classList を基本に、安全・効率的に更新する。closest などの応用で構造変化に強くし、読み取り・書き込みをバッチ化して性能を守る。この感覚を体に入れれば、DOM は“意図通りに動く道具箱”になります。
