JavaScriptでボタンのクリック時の動作を処理する: addEventListenerでイベントを登録する

19, 2020-08-18

目次

JavaScriptでボタンのクリックを処理する

例えば↓のようなHTMLのボタンをクリックしたときに、アラートを表示したいとします。

<button>クリック!</button>

その場合、JavaScriptでは↓のように書くと実現できます。

const btn = document.querySelector('button')
btn.addEventListener('click', () => {
    alert('クリックされました')
})

詳しく解説していきたいと思います。

ボタンを取得し、リスナーを登録する

まず↓の部分ですが、これはdocumentquerySelectorメソッドを使ってbuttonタグを検索し、要素を取得しています。

const btn = document.querySelector('button')
console.log(btn)
// <button>クリック!</button>

HTMLの要素にはリスナーを登録することが出来ます。
リスナーとは、何かイベントが発生したときに呼び出される関数のことです。
今回の場合は、ボタンがクリックされたときにアラートを表示させたいので、アラートを表示させるためのリスナー(関数)を登録します。

要素にリスナーを登録するにはaddEventListenerメソッドを使います。
addEventListenerの第1引数にはイベント名、第2引数にはリスナーを渡すことが出来ます。
よって↓のようにすることで、ボタンのクリック時のリスナーを要素に登録することが出来ます。

btn.addEventListener('click', () => {
    alert('クリックされました')
})

↑の場合、イベント名は「click」を指定し、リスナー内ではalertを呼び出しています。
ボタンがクリックされるとリスナーが呼ばれ、最終的にalertが呼ばれる……という流れになります。

querySelectorの使い方

要素を検索するquerySelectorは第1引数にセレクターとなる文字列を渡します。
タグ名で取得したい場合は↓のように書き、

const btn = document.querySelector('button')

クラス名で取得したい場合は↓のよう書きます。

const btn = document.querySelector('.my-button')

ID名で取得したいなら↓のように書くことが可能です。

const btn = document.querySelector('#my-button')

HTMLのタグの親子関係などを指定することも可能です。

const btn = document.querySelector('div > button')

*正確にはDOMの親子関係ですが、ここではDOMの説明は割愛しています。

addEventListenerの使い方

addEventListenerは第1引数にイベント名、第2引数にリスナーを取ります。
第1引数のイベント名は文字列です。
第2引数は普通の関数かアロー関数を渡します。

普通の関数の場合は↓のようなコードが合法です。

function hello () {
    alert('hello')
}

const btn = document.querySelector('button')
btn.addEventListener('click', hello)
btn.addEventListener('click', function () {
    alert('bye')
})

リスナーは複数登録することが可能です。
複数のリスナーを登録したい場合はaddEventListenerを複数回呼べばOKです。

アロー関数の場合は↓のようなコードが合法です。

const hello = () => {
    alert('hello')
}

const btn = document.querySelector('button')
btn.addEventListener('click', hello)
btn.addEventListener('click', () => {
    alert('bye')
})

↑のJavaScriptを実行したあとにボタンをクリックすると「hello」と「bye」のアラートがそれぞれ呼ばれます。

onclickによる指定

要素にはonclickというプロパティがあり、ここにリスナーを登録することも出来ます。

const btn = document.querySelector('button')
btn.onclick = () => {
    alert('クリックされました')
}

onclickの場合はリスナーを複数登録することが出来ません。
拡張性などを考えるとaddEventListener、手軽さを考えるとonclickに軍配が上がりそうです。

使用例

ボタンのクリックをハンドリングする場合の使用例です。

クラスのメソッドをリスナーにする

クラスのメソッドをリスナーに登録したい場合は↓のようにします。

<button>クリック!</button>

<script>
class Clicker {
    constructor () {
        this.message = 'クリックされました'

        const btn = document.querySelector('button')
        btn.addEventListener('click', this.fire.bind(this))
    }

    fire () {
        alert(this.message)
    }
}

const clicker = new Clicker()
</script>

↓の行に注目してください。

btn.addEventListener('click', this.fire.bind(this))

this.fire.bind(this)という見慣れないコードがありますが、これはfireメソッドにbindの引数をバインドしています。
こうしておくと、リスナーに登録したfireメソッド内で、thisを参照することが出来るようになります。
↑のコードを実行すると「クリックされました」と表示されますが、bindをやめて↓のようにすると

btn.addEventListener('click', this.fire)

「undefined」と表示され意図した動作をしません。
ここら辺のthisの参照方法はJavaScriptのややこしいところなので覚えておきましょう。

リスナーにクロージャ―を登録する

複数のボタンにループ内の添え字を割り当ててalertさせたい場合を考えます。
varを使う場合は↓のようにクロージャ―を作成すればうまくいきます。

<button></button>
<button></button>
<button></button>

<script>
const btns = document.querySelectorAll('button')

for (var i = 0; i < btns.length; i++) {
    const closure = (function () {
        var number = i
        return function () {
            alert(number)
        }
    }())
    const btn = btns[i]
    btn.addEventListener('click', closure)
}
</script>

これはうまくいきますが、ES6以前の古い書き方です。
現代では↓のようにカウント変数にletを使えばクロージャ―を使わなくても期待した動作になります。

<button></button>
<button></button>
<button></button>

<script>
const btns = document.querySelectorAll('button')

for (let i = 0; i < btns.length; i++) {
    const btn = btns[i]
    const func = () => {
        alert(i)
    }
    btn.addEventListener('click', func)
}
</script>

何かの都合でvarを使わなくてはいけない場合は、クロージャ―を使った対処方法を思い出してください。

問題

Q1: ボタンにリスナーを登録する場合、使うべきメソッドを答えよ

  1. filter

  2. querySelector

  3. addEventListener

Q2: querySelectorの第1引数の型を答えよ

  1. 配列

  2. 文字列

  3. オブジェクト

Q3: addEventListenerの第2引数にふさわしいものを答えよ

  1. 配列

  2. 関数

  3. アロー関数


正解はこちら↓

Q1: 2, 3
Q2: 2
Q3: 2, 3