JavaScript DOM操作入門|要素の取得と変更方法
Webページの内容をJavaScriptで動的に変えるには「DOM操作」という技術を使います。ボタンをクリックしたら表示が変わる、フォームの入力内容をチェックするなど、Webサイトのインタラクティブな機能はすべてDOM操作によって実現されています。
DOMとは
DOM(Document Object Model)は、HTMLをJavaScriptから操作するための仕組みです。ブラウザはHTMLを読み込むと、その構造をツリー状のオブジェクト(DOMツリー)として内部的に管理します。JavaScriptはこのDOMツリーを通じてHTML要素にアクセスし、内容の変更やスタイルの操作を行います。
たとえば以下のHTMLは、DOMツリーとして階層的に管理されます。
<div id="app">
<h1>タイトル</h1>
<p class="message">こんにちは</p>
</div>
この構造ではdivが親要素、h1とpがその子要素です。JavaScriptからはこの階層関係をたどって各要素にアクセスできます。
要素の取得
DOM操作の第一歩は、操作したいHTML要素を取得することです。
getElementById
IDを指定して要素を1つ取得します。
// HTML: <h1 id="title">こんにちは</h1>
const title = document.getElementById("title");
console.log(title.textContent); // "こんにちは"
querySelector / querySelectorAll
CSSセレクタを使って要素を取得します。最も汎用的な方法です。
// 最初に一致する要素を1つ取得
const message = document.querySelector(".message");
const firstItem = document.querySelector("ul li");
// 一致する要素をすべて取得(NodeListが返る)
const allItems = document.querySelectorAll("ul li");
allItems.forEach((item) => {
console.log(item.textContent);
});
querySelectorはCSSセレクタをそのまま使えるため、柔軟な指定が可能です。
// さまざまなセレクタが使える
document.querySelector("#header .nav-item:first-child");
document.querySelector("input[type='email']");
document.querySelector(".card > p");
要素の内容とスタイルの変更
テキストの変更
const heading = document.querySelector("h1");
// テキスト内容を変更
heading.textContent = "新しいタイトル";
// HTMLを含む内容を変更(XSSに注意)
heading.innerHTML = "重要な<strong>お知らせ</strong>";
textContentは純粋なテキストとして扱い、innerHTMLはHTMLタグも解釈されます。ユーザーの入力をそのままinnerHTMLに入れるとセキュリティ上の問題(XSS)が生じるため、基本的にはtextContentを使いましょう。
スタイルの変更
const box = document.querySelector(".box");
// 個別のスタイルを変更
box.style.backgroundColor = "#f0f0f0";
box.style.padding = "20px";
box.style.borderRadius = "8px";
// CSSクラスの操作(推奨)
box.classList.add("active");
box.classList.remove("hidden");
box.classList.toggle("open"); // あれば削除、なければ追加
個別のスタイル変更よりも、CSSクラスの追加・削除で見た目を変える方が保守性が高くおすすめです。スタイルはCSSファイルに定義し、JavaScriptはクラスの付け替えだけを行うのが理想的です。
属性の操作
const link = document.querySelector("a");
// 属性の取得
console.log(link.getAttribute("href"));
// 属性の設定
link.setAttribute("href", "https://example.com");
link.setAttribute("target", "_blank");
// 属性の削除
link.removeAttribute("target");
// img要素のsrcを変更
const img = document.querySelector("img");
img.src = "new-image.jpg";
img.alt = "新しい画像の説明";
イベント処理
イベント処理は、ユーザーの操作(クリック、入力、スクロールなど)に反応してプログラムを実行する仕組みです。
addEventListener
const button = document.querySelector("#myButton");
button.addEventListener("click", () => {
console.log("ボタンがクリックされました");
});
よく使うイベント
// クリックイベント
document.querySelector("#btn").addEventListener("click", () => {
alert("クリックされました");
});
// 入力イベント(リアルタイム)
document.querySelector("#nameInput").addEventListener("input", (event) => {
const output = document.querySelector("#preview");
output.textContent = event.target.value;
});
// フォーム送信イベント
document.querySelector("#form").addEventListener("submit", (event) => {
event.preventDefault(); // デフォルトの送信を止める
const formData = new FormData(event.target);
console.log(formData.get("email"));
});
// ページ読み込み完了イベント
document.addEventListener("DOMContentLoaded", () => {
console.log("ページの読み込みが完了しました");
});
event.preventDefault()は、ブラウザのデフォルト動作(フォーム送信によるページ遷移など)を止めるときに使います。
実践例: カウンターアプリ
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>カウンター</title>
<style>
.counter {
text-align: center;
margin-top: 50px;
font-family: sans-serif;
}
.count {
font-size: 48px;
margin: 20px 0;
}
button {
font-size: 18px;
padding: 10px 20px;
margin: 0 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="counter">
<h1>カウンター</h1>
<div class="count" id="count">0</div>
<button id="decrement">-1</button>
<button id="reset">リセット</button>
<button id="increment">+1</button>
</div>
<script>
let count = 0;
const countDisplay = document.querySelector("#count");
const updateDisplay = () => {
countDisplay.textContent = count;
};
document.querySelector("#increment").addEventListener("click", () => {
count++;
updateDisplay();
});
document.querySelector("#decrement").addEventListener("click", () => {
count--;
updateDisplay();
});
document.querySelector("#reset").addEventListener("click", () => {
count = 0;
updateDisplay();
});
</script>
</body>
</html>
このコードをHTMLファイルとして保存してブラウザで開くと、動作するカウンターアプリが確認できます。
よくある間違いと対策
間違い1: 要素が取得できない
// NG: HTMLの読み込み前にスクリプトが実行される
// <head>内の<script>で要素を取得しようとすると null になる
// OK: DOMContentLoadedを使う
document.addEventListener("DOMContentLoaded", () => {
const title = document.querySelector("h1");
console.log(title.textContent);
});
// OK: scriptタグをbodyの最後に置く
// <body>
// <h1>タイトル</h1>
// <script src="main.js"></script>
// </body>
JavaScriptはHTMLよりも先に実行されることがあります。DOMContentLoadedイベントを使うか、<script>タグを<body>の最後に配置しましょう。
間違い2: querySelectorAllの戻り値
// querySelectorAllはNodeListを返す(配列ではない)
const items = document.querySelectorAll(".item");
// NG: 配列メソッドは直接使えない場合がある
// items.map(item => item.textContent);
// OK: forEachは使える
items.forEach((item) => {
console.log(item.textContent);
});
// OK: 配列に変換してから使う
const itemArray = Array.from(items);
const texts = itemArray.map((item) => item.textContent);
間違い3: イベントリスナーの重複登録
// NG: ループ内で毎回リスナーを登録すると重複する
// for (let i = 0; i < 3; i++) {
// button.addEventListener("click", handler);
// }
// OK: 一度だけ登録する
function handleClick() {
console.log("クリック");
}
button.addEventListener("click", handleClick);
DOM操作はJavaScriptの中でも実用性が高い分野です。まずはこの記事のカウンターアプリを改造して、色を変えたりテキストを追加したりして、自分なりの機能を実装してみてください。