クリックに反応する
このレッスンで分かること
addEventListenerは「どの要素で」「どの出来事が起きたら」「何をするか」を結び付けます- 第 2 引数に渡すのは関数そのもので、丸かっこを付けて呼んではいけません
開いた瞬間の一度きりで、あとは静まりかえっている
第8章で書いた JavaScript は、どれもページが読み込まれた瞬間に上から下まで走って、それで終わりでした。カードを描き終えたら、あとは何も起きません。見ている人がボタンを押しても、文字を打っても、画面は静まりかえったままです。
その静けさを破るのがイベント処理です。イベントとは、ブラウザの中で起きた出来事のことです。押された、キーが打たれた、読み込みが終わった。ブラウザはこうした出来事のたびに「いま click が起きました」という知らせを出しています。私たちがやるのは、その知らせを聞いて動く処理を、あらかじめ登録しておくことだけです。
JavaScript
const title = document.querySelector("h1");
title.addEventListener("click", function () {
console.log("見出しが押されました");
});読み解くと、3 つの部品でできています。どの要素で起きた出来事を見るのかを表す title、どの出来事を待つのかを表す "click"、そして起きたときに動く第 2 引数の関数です。日本語に直すと「title で click が起きたら、この関数を動かして」となります。
3 つがそろって、はじめて反応が生まれます。どれか 1 つでも名前を間違えると、エラーも出ないまま静かに何も起きません。イベント処理のつまずきの大半は、この「静かに何も起きない」に由来します。
知らせは、聞いている人がいなくても常に流れています。ボタンを押せば click は必ず起きています。何も起きないように見えるのは、受け取る処理を誰も登録していないからです。イベント処理は、出来事をつくる作業ではなく、すでに流れている出来事を拾う作業だと考えると全体像がつかめます。
丸かっこを付けると、開いた瞬間に 1 回だけ動く
第6章で学んだコールバック関数が、ここで本当に効いてきます。第 2 引数は、あとで呼んでもらうための関数です。自分では呼びません。
JavaScript
function logClick() {
console.log("押されました");
}
title.addEventListener("click", logClick); // 正しい
title.addEventListener("click", logClick()); // 間違い丸かっこは「いま実行しろ」という命令です。付けて書くと、ページを開いた瞬間に logClick が 1 回動いてしまい、その戻り値 (たいてい undefined) が addEventListener に渡ります。結果として、押しても何も起きないのに開いた瞬間だけ勝手に動く、という不思議な挙動になります。
その場に処理を書き下ろすなら、アロー関数をそのまま置いても構いません。同じ処理を複数の要素に付けるなら名前を付けて使い回し、その場限りなら無名関数にする、という選び分けが多いです。
同じボタンに 2 つの処理を付けたい
addEventListener は、同じ要素の同じイベントに何本でも重ねられます。
JavaScript
title.addEventListener("click", logClick);
title.addEventListener("click", () => {
console.log("2 つ目も動きます");
});HTML の属性としてイベントを書く方法もあります。<button onclick="logClick()"> のような書き方です。短くて手軽ですが、こちらは 2 つ目を書くと 1 つ目が上書きされます。いまの現場でほとんど使われないのは、そのためです。
| 見るところ | onclick 属性 | addEventListener |
|---|---|---|
| 書く場所 | HTML の中 | JavaScript の中 |
| 同じイベントに複数 | あとから書いたほうで上書きされる | いくつでも重ねられる |
| 役割の分かれ方 | 構造と動きが混ざる | 構造と動きが分かれる |
第8章でやったように、HTML を JavaScript から描き出すようになると、そもそも属性を書く場所がありません。最初から addEventListener で書く癖を付けておくのが、結局いちばん楽です。
よくある間違い
- イベント名に
onを付ける — 渡すのは"click"です。"onclick"や"Click"と書いてもエラーは出ず、一生起きないイベントを黙って待ち続けます - 要素を掴む行で綴りを間違える — id が 1 文字違うと変数は
nullになり、Cannot read properties of nullで止まります。エラーが指すのはaddEventListenerの行ですが、本当の原因は 1 行上にあります typeを書かないボタンを使う —button要素の既定は送信ボタンです。フォームの中に置いたときに勝手にページが再読み込みされるので、type="button"を付ける癖にしておきます
課題
- HTML の
#aboutの中にid="hello-button"type="button"class="submit-button"のボタンを足し、文字は「あいさつする」にする - そのすぐ下に
id="hello-message"の空のpを足す - JavaScript で
#hello-buttonにclickを登録し、#hello-messageのtextContentに「こんにちは。山田 太郎です。」を入れる - 第 2 引数には関数そのものを渡す。丸かっこを付けて呼ばない