Day17 後半のゴール
後半では、click イベントを
「ただのきっかけ」から「アプリの動きを司る中心」まで引き上げます。
前半で学んだ addEventListener(“click”, …) を、
DOM 操作(textContent / createElement / appendChild)と組み合わせて、
「クリックで画面が変わる」パターンを自分で設計できるようになることがゴールです。
Day17 後半でつかみたい感覚
クリックは“状態を変えるスイッチ”であり、その結果として画面が変わる
「状態(変数)」「イベント(click)」「DOM操作」をセットで考える
ここが腹に落ちると、
「ボタンを置いたら、とりあえず何か面白いことができる」という感覚になります。
クリックで状態を切り替える復習と深掘り
押すたびに ON / OFF を切り替える
まずはシンプルな「ON / OFF 切り替えボタン」を作ります。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Day17 イベント処理 後半</title>
</head>
<body>
<h1 id="status">OFF</h1>
<button id="toggleButton">切り替え</button>
<script>
const statusElement = document.getElementById("status");
const toggleButtonElement = document.getElementById("toggleButton");
let isOn = false;
toggleButtonElement.addEventListener("click", () => {
isOn = !isOn;
if (isOn) {
statusElement.textContent = "ON";
} else {
statusElement.textContent = "OFF";
}
});
</script>
</body>
</html>
ここでの本質は、「クリックされた瞬間に画面を変える」のではなく、
「クリックされた瞬間に状態(isOn)を変え、その状態に応じて画面を変える」という流れになっていることです。
クリック
→ 状態を更新(isOn を反転)
→ 状態に応じて textContent を更新
この三段階を意識できると、
アプリの動きが頭の中で整理しやすくなります。
状態と表示を関数で分ける
もう一歩整理して、表示更新を関数に切り出してみます。
let isOn = false;
function updateStatus() {
if (isOn) {
statusElement.textContent = "ON";
} else {
statusElement.textContent = "OFF";
}
}
toggleButtonElement.addEventListener("click", () => {
isOn = !isOn;
updateStatus();
});
updateStatus();
JavaScriptこの形にすると、
「クリックは状態を変えるだけ」「画面更新は updateStatus が担当」という役割分担がはっきりします。
状態を変える処理
状態から画面を作る処理
この二つを分けておくと、
後から仕様変更が入っても壊れにくいコードになります。
クリックと createElement / appendChild を組み合わせる
クリックで新しい要素を追加する
Day16 で学んだ createElement / appendChild と click イベントを組み合わせると、
「クリックするたびに要素が増える」動きを作れます。
例として、「ログを追加するボタン」を作ってみます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Day17 イベント処理 後半</title>
</head>
<body>
<h1>クリックログ</h1>
<button id="logButton">ログを追加</button>
<div id="logContainer"></div>
<script>
const logButtonElement = document.getElementById("logButton");
const logContainerElement = document.getElementById("logContainer");
let count = 0;
logButtonElement.addEventListener("click", () => {
count += 1;
const p = document.createElement("p");
p.textContent = `ボタンが ${count} 回クリックされました。`;
logContainerElement.appendChild(p);
});
</script>
</body>
</html>
ここでは、click イベントが「新しい要素を作るトリガー」になっています。
クリック
→ count を増やす
→ createElement で p を作る
→ textContent にメッセージを入れる
→ appendChild で logContainer に追加
クリックが「状態の変化」と「DOM の変化」の両方を引き起こしている、という構造です。
セキュリティの視点:ユーザー入力を使うとき
もし、ユーザーが入力した文字列をログに含める場合も、
textContent を使っていれば安全側に倒せます。
const inputElement = document.getElementById("textInput");
logButtonElement.addEventListener("click", () => {
const text = inputElement.value;
const p = document.createElement("p");
p.textContent = `入力: ${text}`;
logContainerElement.appendChild(p);
});
JavaScripttextContent は、<script>...</script> のような文字列も「ただの文字」として扱うため、
スクリプトが実行されることはありません。
click イベントと DOM 操作を組み合わせるときほど、
innerHTML を安易に使わない意識が重要になります。
複数のクリックイベントで役割を分ける
「追加」と「クリア」の二つのボタン
次は、二つのボタンを用意して、
片方は「追加」、もう片方は「クリア」という役割にしてみます。
<h1>メモログ</h1>
<input id="memoInput" type="text">
<button id="addButton">追加</button>
<button id="clearButton">クリア</button>
<div id="memoContainer"></div>
JavaScript はこう書けます。
const memoInputElement = document.getElementById("memoInput");
const addButtonElement = document.getElementById("addButton");
const clearButtonElement = document.getElementById("clearButton");
const memoContainerElement = document.getElementById("memoContainer");
addButtonElement.addEventListener("click", () => {
const text = memoInputElement.value;
if (text === "") {
return;
}
const p = document.createElement("p");
p.textContent = text;
memoContainerElement.appendChild(p);
memoInputElement.value = "";
});
clearButtonElement.addEventListener("click", () => {
memoContainerElement.textContent = "";
});
JavaScriptここでのポイントは、
「それぞれのボタンに、それぞれの click イベントを付けている」ことです。
追加ボタンの click
→ 新しい p を作って appendChild
クリアボタンの click
→ memoContainer の中身を空文字にして、子要素を全部消す
click イベントは「1つのボタンに1つだけ」ではなく、
複数のボタンにそれぞれ別の処理を割り当てられる、という感覚を持っておくと良いです。
イベントオブジェクトに軽く触れておく
event 引数で「何が起きたか」の情報を受け取れる
click イベントのハンドラは、
実は「イベントオブジェクト」と呼ばれる情報を受け取ることができます。
button.addEventListener("click", (event) => {
console.log(event);
});
JavaScriptこの event には、
どの要素がクリックされたか
どの座標でクリックされたか
修飾キー(Ctrl / Shift など)が押されていたか
といった情報が入っています。
Day17 の段階では「そういうものがある」くらいで十分ですが、
「イベントハンドラの第一引数には event が来る」という形だけ覚えておくと、
後でキーボードイベントやマウスイベントを扱うときにスムーズです。
ありがちなつまずきと対処
addEventListener の書き方ミス
よくあるミスの一つが、
関数を「呼び出して」渡してしまうパターンです。
// よくある間違い
button.addEventListener("click", handleClick());
JavaScriptこれだと、addEventListener を呼んだ瞬間に handleClick が実行され、
戻り値(たいてい undefined)がイベントハンドラとして登録されてしまいます。
正しくは「関数そのもの」を渡します。
button.addEventListener("click", handleClick);
JavaScriptあるいは無名関数で書くなら、こうです。
button.addEventListener("click", () => {
handleClick();
});
JavaScript「関数を渡す」と「関数を呼び出す」の違いを意識できると、
イベント処理のバグがかなり減ります。
要素がまだ存在しないタイミングでイベントを付けようとする
script を head の中に書いていて、
まだ body の要素が読み込まれていないタイミングで
getElementById してしまうと、null になります。
Day17 の段階では、
基本的に script は body の一番下に置く、
というルールにしておくと安全です。
<body>
<!-- 要素たち -->
<script>
// ここなら、上の要素が読み込まれた後に実行される
</script>
</body>
それでも不安なら、
null チェックを入れておくのも良い習慣です。
Day17 後半のミニサンプル:全部入り
クリックで追加・カウント・クリアを行う小さなアプリ
最後に、Day15〜Day17 の内容をまとめた
小さな「クリック練習アプリ」を書いてみます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Day17 イベント処理 総合ミニアプリ</title>
</head>
<body>
<h1 id="title">クリック練習アプリ</h1>
<p>
メモ:<input id="memoInput" type="text">
<button id="addButton">追加</button>
<button id="clearButton">クリア</button>
</p>
<p id="countText">追加回数: 0</p>
<div id="memoContainer"></div>
<script>
const titleElement = document.getElementById("title");
const memoInputElement = document.getElementById("memoInput");
const addButtonElement = document.getElementById("addButton");
const clearButtonElement = document.getElementById("clearButton");
const countTextElement = document.getElementById("countText");
const memoContainerElement = document.getElementById("memoContainer");
let count = 0;
addButtonElement.addEventListener("click", () => {
const text = memoInputElement.value;
if (text === "") {
titleElement.textContent = "メモを入力してください。";
return;
}
const p = document.createElement("p");
p.textContent = text;
memoContainerElement.appendChild(p);
count += 1;
countTextElement.textContent = `追加回数: ${count}`;
titleElement.textContent = "メモを追加しました。";
memoInputElement.value = "";
});
clearButtonElement.addEventListener("click", () => {
memoContainerElement.textContent = "";
count = 0;
countTextElement.textContent = "追加回数: 0";
titleElement.textContent = "メモをクリアしました。";
});
</script>
</body>
</html>
ここには、Day17 までの要素がほぼ全部入っています。
click イベント
状態管理(count)
textContent の更新
createElement / appendChild
入力値のチェック
複数ボタンへのイベント登録
このレベルのコードが「自分で考えて書ける」ようになると、
もう立派に「小さな Web アプリを作れる人」です。
Day17 後半のまとめ
click イベントは、
「ユーザーの操作をきっかけに、状態と画面を変えるスイッチ」です。
後半では、
クリックで状態を切り替える(ON / OFF)
状態と表示を関数で分ける
クリックで新しい要素を追加する
複数のボタンにそれぞれ click イベントを付ける
イベントオブジェクトの存在を知る
関数を“渡す”ことと“呼び出す”ことの違いを意識する
ところまで踏み込みました。
ここまで来たあなたは、
「クリックされたら何をしたいか」を自分で設計し、
コードに落とし込める段階にいます。
この感覚は、この先のキーボードイベントやフォーム送信、
さらには非同期処理とも自然につながっていきます。
