第9章(最終章) JavaScriptのイベント処理入門
初学者向けの入門講座もこの章が最終章です。
このページでは、JavaScriptのイベントという言葉が指すものはなんなのか、イベントに常に聞き耳を立てているリスナーと、関数の登録の方法について解説しています。
前回までの講座で、
- 第1章 JavaScriptでのブラウザ版VSCode入門
- 第2章 JavaScriptと蜜月の関係であるHTMLとCSS入門
- 第3章 JavaScriptの実行方法入門
- 第4章 JavaScriptの変数入門
- 第5章 JavaScriptの関数入門
- 第6章 JavaScriptのオブジェクト入門
- 第7章 JavaScriptの条件分岐処理入門
- 第8章 JavaScriptの配列と繰り返し処理入門
について学びました。今回はそれらを一読された前提での続編になります。
目次
学習用コード
以下のindex.htmlとindex.jsファイルの内容をこの章の学習の出発点にします。
※ 一応これらファイルを自サーバーに準備してあります。必要な方はダウンロードして解凍してください。(ファイルの解凍方法は第1章のファイルの展開(解凍)方法で触れています)
第9章の学習用ファイル(chapter09.zip)をダウンロード
<!DOCTYPE html>
<html>
<head>
<title>chapter09</title>
</head>
<body>
<p>与えられた数xの2乗は?</p>
<label for="x">x: </label>
<input type="number" id="x" value="0" />
<button id="keisan_btn">計算</button>
<p id="answer">0</p>
<script src="js/index.js"></script>
</body>
</html>
let x = document.getElementById("x");
let keisan_btn = document.getElementById("keisan_btn");
let answer = document.getElementById("answer");
// 発火したら実行してほしい関数
// 2乗は英語でsquared
let squared = () => {
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのPタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
};
// イベントリスナー
keisan_btn.addEventListener("click", squared);
index.htmlをブラウザで開くと以下のようになります。(※ブラウザで開く方法は第1章のhtmlファイルをブラウザで開く方法で触れています)
xという入力フォームに入力された値の2乗を計算してその下に表示します。
xに2を入力して計算ボタンをクリックすると、4が表示されます。
これまでの講座で初登場となるHTMLのinputタグとlabelタグ、buttonタグについて簡単に説明します。
サンプルコードのこの部分です。
<label for="x">x: </label>
<input type="number" id="x" value="0" />
<button id="keisan_btn">計算</button>
label(ラベル)タグはそのままの意味です。中身が何かを表示するためのものです。我が家のとんかつソースのラベル・・・
labelタグのfor属性に、次に続くinputタグのidを指定すると、labelタグをクリックしたらinputタグの入力欄にカーソルが移動する仕様になっています。
inputタグはtype属性にnumberを指定しています。
数値を入力するならtype="number"、文字列ならtype="text"とか、あと、チェックボックス(type="checkbox")やラジオボタン(type="radio")もinputの仲間です。他にも用途に合わせて色々あります。詳細はここが詳しいです。
<input>: 入力欄(フォーム入力)要素 - HTML: ハイパーテキストマークアップ言語 | MDN
buttonタグもそのままの見た目の意味ですね。ボタンが複数あってもどのボタンがクリックされたのかを区別するためにid(keisan_btn)を割り振っています。
この時の、「ボタンがクリックされた」ことをイベントといいます。
イベントとは?
ブラウザ上での様々な出来事をイベントと呼びます。
以下のようなユーザーの操作
- ボタンがクリックされた
- 入力フォームになにか入力された
- マウスがある要素の上に乗った(Amazonで商品画像の上にマウスを乗せた時とか)
その他に、「ページの読み込みが完了した」などのブラウザ自身の出来事もイベントとして扱われます。
つまり、ブラウザ上で発生した様々な出来事を総称して「イベント」と呼んでいます。
さらに、イベントが発生したことを俗に「発火した」といいます。
「計算ボタンをクリックしたらイベントが発火した」のように使います。よく使われる言葉ですので否が応でも覚えると思います。
イベントリスナー
特定のラジオ番組に聴衆・聞き手いわゆる「リスナー」がいるように、JavaScriptのイベントに耳をすましている「リスナー」がいます。
そのリスナーに、発火したら実行してほしい関数を事前に登録することができます。
「ボタンがクリックされたらこの関数を実行・・・」が典型的な例です。
そのような典型例のサンプルコードの、
let x = document.getElementById("x");
let keisan_btn = document.getElementById("keisan_btn");
let answer = document.getElementById("answer");
// 発火したら実行してほしい関数
// 2乗は英語でsquared
let squared = () => {
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのPタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
};
// イベントリスナー
keisan_btn.addEventListener("click", squared);
この部分がリスナーになります。
// イベントリスナー
keisan_btn.addEventListener("click", squared);
意味は「idがkeisan_btnなボタン要素でclickイベントが発火したらsquared関数を実行してね」となります。
サンプルコードのidはこのように割り振られています。
squared関数では、
まず、入力フォームxの値はxのvalueプロパティに格納されているのでそれを変数x_numに代入しています。
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
次に、idがanswerなPタグの文字列を書き換えるためにinnerTextプロパティにx_numを2乗した値を代入しています。
// idがanswerのPタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
innerTextプロパティとは、要素の文字列が格納されているプロパティです。
<p>文字列</p>の「文字列」の部分に該当します。
inputイベント
「入力フォームになにか入力した」のもイベントになりますので、入力をきっかけにsquared関数を実行することもできます。
サンプルコードの最後に以下のコードを追記して、
// inputイベントリスナー
x.addEventListener("input", squared);
実行すると、計算ボタンをクリックしなくても、入力フォームの値を変更するたびに即座にその値の2乗が計算されて表示されます。
click, inputの他にも様々なイベントがあります。「javascript イベント一覧」でググれば調べられます。
登録する関数は無名関数でもいい
というか、無名関数で書かれているコードが多いと思います。
無名関数とはあえて名前をつけない関数のことです。特に名前が必要でないなら、名前を考えずに省略できるということです。
2乗する関数だったら、「英語で2乗ってなんだろう?」って考えてsquaredを関数名にして、このように書きます。
function squared() {
}
// もしくはアロー関数で
let squared = () => {
}
無名関数は関数名に悩まなくて済みます。そして、このような書き方になります。
function() {
}
// もしくはアロー関数で
() => {
}
サンプルコードを無名関数で書き直すとこのようになります。スッキリしますね。
keisan_btn.addEventListener("click", () => {
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのspanタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
});
イベントリスナーに登録した関数の引数に渡されるEventオブジェクト
イベントリスナーの無名関数の引数には、発生したイベントに関する情報がセットになったEventオブジェクトが渡されます。
クリックされた時のマウスカーソルの位置(x, y座標)や、クリックされた要素の情報などです。
実際にやってみましょう。
JSファイルをこのように書き換えました。関数の引数にはEventオブジェクトが渡されるので慣例的にeventかeがよく使われます。ここではeとします。
let x = document.getElementById("x");
let keisan_btn = document.getElementById("keisan_btn");
let answer = document.getElementById("answer");
keisan_btn.addEventListener("click", (e) => {
// 渡されたEventオブジェクトをコンソールで確認。
console.log(e);
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのspanタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
});
ブラウザで実行してボタンをクリックしてコンソールで確認します。
クリック時のマウスカーソルの位置(x, y座標)は、それぞれclientX, clientY
クリックされた要素は、target
コードとしてこのEventオブジェクトの3つのプロパティにアクセスしてみます。といっても普通のオブジェクト同様、ドット記法でアクセスするだけです。
keisan_btn.addEventListener("click", (e) => {
// Eventオブジェクトのプロパティ
console.log("x座標", e.clientX);
console.log("y座標", e.clientY);
console.log("buttonタグ", e.target);
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのspanタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
});
実行してボタンをクリックすると、
buttonタグはe.targetでアクセスしましたが、このe.targetはgetElementByIdメソッドで取得したものと同じものです。
let keisan_btn = document.getElementById("keisan_btn");
と
e.target
は同じ。
HTML要素の文字列はinnerTextで取得できるので、ボタンをクリックしたら「計算」というボタンの文字を他の文字(たとえば2乗した答えとか)に差し替えることができます。
やってみます。最後の行のコードがそれです。
let x = document.getElementById("x");
let keisan_btn = document.getElementById("keisan_btn");
let answer = document.getElementById("answer");
keisan_btn.addEventListener("click", (e) => {
// xフォームの値を取得して変数x_numに格納。
let x_num = x.value;
// idがanswerのspanタグの内容をxを2乗した値に書き換える。
answer.innerText = x_num * x_num;
// ボタンの文字をxを2乗した値に書き換える。
e.target.innerText = x_num * x_num; // <- 追加したコード
});
今回学んだことをクイズゲームで確認しよう!
このページで解説したことを全問のクイズ形式のゲームにしました。
ゲーム感覚で復習すると記憶に定着する助けになります。
下の「クイズを開始」ボタンでゲームを開始すると「YES」「NO」ボタンが現れますので、上から降ってくる問題が正しければ「YES」を、間違っているなら「NO」ボタンを押してください。
まとめ
「ボタンをクリックした」など、ブラウザでの出来事をイベントと呼び、イベントが発生したことを俗に「発火」といい、イベントリスナーはイベントが発火するのを常に聞き耳を立てていて、リスナーに関数を登録すれば発火した時に実行されることがわかりました。