コース一覧
JavaScriptでWebページを動かす
event オブジェクト

JavaScriptでWebページを動かす

DOM から要素を取得・更新・追加し、クリック・入力・フォーム送信に反応する処理を作る全 20 レッスン(411 分)のコースです。タイマーと localStorage も使い、最後は入力を保存できるひとことメモを仕上げます。用意された HTML/CSS を使うため、学習の中心は JavaScript です。

1
DOM のきほん
01. DOM とは何か15分
02. 要素を取得する20分
03. テキストを書き換える20分
04. class を付け外しする20分
05. 要素を作って追加する20分
06. 配列から一覧を描画する25分
07. つくる ギャラリーをデータ駆動にする30分
08. 第1章まとめクイズ10分
2
イベント処理
01. クリックに反応する18分
02. event オブジェクト20分
03. 入力欄の値を取る18分
04. フォーム送信を制御する20分
05. つくる ダークモード切替25分
06. つくる フォームの入力チェック25分
07. 第2章まとめクイズ10分
3
タイマーと総合制作
01. setTimeout と setInterval20分
02. localStorage で保存する20分
03. つくる ひとことメモウィジェット30分
04. 自由拡張30分
05. 完成と次のステップ15分

event オブジェクト

target と currentTarget
解説

このレッスンで分かること

  • イベントの処理には、出来事の情報が入った event が第 1 引数で渡されます
  • event.target は実際に押された要素で、登録した要素と同じとはかぎりません

押されたことは分かる。どれが押されたかが分からない

前回のボタンは 1 つだけでした。押されたら決まった文字を出せばよかったので、それ以上の情報は要りません。ところが作品の一覧には、いまカードが 5 枚ならんでいます。しかも配列から描いているので、データを足せば 10 枚にも 20 枚にも増えます。押されたかどうかだけでは足りず、どれが押されたかを知る必要があります。

その答えが event オブジェクトです。イベントが起きたとき、ブラウザは処理の関数を呼ぶだけでなく、その出来事に関する情報をまとめたオブジェクトを第 1 引数として渡してくれます。要らなければ書かなくてかまいません。要るときは引数名を 1 つ書くだけです。

JavaScript

const table = document.querySelector(".skill-table"); table.addEventListener("click", function (event) { console.log(event.type); // "click" console.log(event.target); // 実際に押された要素 });

引数の名前は何でも動きますが、event か e と書くのが慣習です。この教材では event で統一します。自分でつくって渡すものではないので、引数を書き忘れても undefined になるだけで、次の行の event.target ではじめて止まります。

押したのは行なのに、返ってくるのはセル

スキル表のセルを押してみてください。event.target に入っているのは td です。行の tr ではありません。target は、いちばん内側で出来事が起きた要素だからです。

いっぽう event.currentTarget は、addEventListener を書いた相手を指します。.skill-table に登録したなら、どこを押しても .skill-table のままです。

プロパティ何が入るか
target実際に出来事が起きた、いちばん内側の要素
currentTargetaddEventListener を付けた側の要素
typeイベントの種類の文字列

target をそのまま判定に使うと、押した場所で結果が変わってしまいます。見出しを押したのか、説明文を押したのか、余白を押したのかで、3 通りに分かれます。そこで closest をはさみます。

JavaScript

const row = event.target.closest("tr");

closest は、その要素から親をたどって、条件に合う最初の要素を返します。td から始めても、その親の tr にたどり着きます。どこを押しても同じ相手にそろえられるので、判定はここから始めます。

あとから増えたカードには、登録が付いていない

カードが 5 枚あるなら、5 枚それぞれに addEventListener を付ければよさそうに見えます。ところが第8章で、カードは配列から JavaScript が描くようになりました。あとから増えたカードには、登録済みの処理は付いていません。増えるたびに登録し直す面倒がついてまわります。

そこで、親にまとめて 1 つだけ登録します。イベント委譲と呼ばれるやり方です。

JavaScript

table.addEventListener("click", function (event) { const row = event.target.closest("tr"); if (!row) { return; } row.setAttribute("data-picked", "yes"); });

クリックは、押された要素から親へ順に伝わっていきます。この伝わり方をバブリングと呼び、イベント委譲はその性質をそのまま使っています。子で起きた出来事が親まで届くから、親で待ち構えていられます。

登録は最初の 1 回だけです。あとから行が何行増えても、押せばそのまま反応します。表の見出しの外や、行と行のすき間を押したときは closest が null を返すので、早期 return で抜けます。100 行の一覧でも登録は 1 回、処理は 1 本です。

よくある間違い

  • 引数を書き忘れる — function () { のまま中で event を使うと event is not defined で止まります。丸かっこの中に event と書き足します
  • closest をはさまずに target を使う — 説明文を押したときの event.target は p です。その中に見出しは無いので、querySelector は null を返し、次の行で止まります。まず closest で目的の要素まで戻します
  • 外側を押したときを考えていない — すき間を押すと closest は null です。if (!row) return; の 1 行を入れるだけで防げます

課題

  1. HTML の #works の中、.work-list のすぐ下に id="work-message" の空の p を足す
  2. JavaScript で .work-list に click を 1 つだけ登録する
  3. 処理の引数に event を受け取り、event.target.closest(".work-card") で押されたカードを特定する
  4. カードが見つからなければ早期 return し、見つかれば中の h3 の文字を使って「〇〇 を選びました」と表示する

ヒント

登録する相手はカードではなく、その親の `.work-list` です。カードは JavaScript が描くので、親に付けるほうが確実です

処理は `function (event) { ... }` の形にして、`event.target.closest(".work-card")` を使います

カードのすき間を押すと `closest` は `null` を返します。`if (!card) { return; }` を先に置いてください

index.html
style.css
script.js
プレビュー

できているか

  • #work-message の段落がある
  • #work-message が作品のところにある
  • 第8章で描いた作品カードがそのまま残っている
  • 1 枚目のカードを押すと題名が出る
  • 2 枚目のカードを押すと表示が入れ替わる
エディタを読み込んでいます