jQueryのイベント設置: セレクタ指定の有無で何が変わる？

jQueryでイベントを設置・削除する際に`.on`と`.off`をよく使用します。
これらのメソッドの第二引数にセレクタを指定する場合としない場合の違いをまとめました。

## 1.jQueryでイベントを設置する
jQueryでイベントを設置するには`.on`メソッドを使用します。

```javascript
.on(events, [selector,] [data,] handler(eventObject))
```
- 必須：`events`には`click`や`keyup`などのイベント名を指定
- 任意：`selector`はイベントを発生させたいセレクタを指定
- 任意：`data`にはイベントに渡したいデータを指定
- 必須：`handler`はイベントが発生した際の処理を指定



### 1-1. セレクタを省略してイベントを設置する
セレクタを省略する場合、例えばボタンをクリックしたときにアラートを表示するには以下のように書けます。
```javascript
$('button').on('click', function() { alert('hello world'); });
```
クラスやID属性を直接参照することもできます。
```javascript
$('#primary').on('click', function() { alert('hello world'); });
$('.js-click-here').on('click', function() { alert('hello world'); });
```
この場合、イベントは`.on`メソッドを呼び出している`$('button')`自身に設置されます。

> セレクタ引数を省略、またはnullを指定するとイベントハンドラは選択された要素を直接参照するようになります。

:::note info
セレクタを省略した場合、イベントの設置場所は選択された要素自身になります。
:::

### 1-2. セレクタを指定してイベントを設置する
セレクタに要素を指定することもできます。例えば以下のように書けます。
```javascript
$('body').on('click', 'button', function() { alert('hello world'); });
```

クラスやID属性を指定することも可能です。
```javascript
$('body').on('click', '#primary', function() { alert('hello world'); });
$('body').on('click', '.js-click-here', function() { alert('hello world'); });
```
この場合、イベントは`$('body')`に設置されますが、イベントはその要素内でセレクタにマッチした部分で発生します。

> セレクタが指定されれば、選択要素を直接参照するのはなく、delegateのようにそのセレクタにマッチした部分でイベントが発生した場合に イベントハンドラを実行するようになります。

:::note info
セレクタを指定した場合、イベントはセレクタにマッチした要素で発生します。
:::


## 2. 選択要素とセレクタの違い
選択要素は`.on`メソッドが呼ばれる前に、ページ上に存在している必要があります。
後から動的に生成した要素を指定するとイベントは実行されません。

> .on()では選択要素とセレクターがありますが、選択要素は.onメソッドが呼ばれる前にページ上に存在している必要があります。

以下のコードでは`$('button')`は`.on`メソッドが呼ばれる前に存在している必要があります。
```javascript
$('button').on('click', function() { alert('hello world'); });
```
セレクタは後から動的に生成した要素にも有効です。


>  もし新しい要素が後からjavaScriptの動的な処理によって選択要素内に追加されたとしても、 セレクタにマッチしていればその新しい要素に対してもイベントハンドラが有効になります。

以下のコードでは、セレクタで指定されたボタンは後から生成されてもイベントが発生します。
```javascript
$('body').on('click', 'button', () => { alert('hello world'); });
```

:::note info
動的に追加された要素にイベントを設置したい場合は、その要素をセレクタに指定します。
:::



## 3. イベントの削除方法
`.on`で設置したイベントを削除するには`.off`メソッドを使用します。


### 3-1 直接参照しているイベントを削除する
セレクタを指定せずにボタンタグが直接参照されている場合は以下のように記述します。
```javascript
$('button').on('click', function() { alert('hello world'); });
$('button').off('click);
```
クラスやID属性を指定して削除することも可能です。
```html
<button id="primary" class="js-click-here">Click here</button>
```
```javascript
$('#primary').off('click');
$('.js-click-here').off('click');
```

### 3-2 セレクタを指定しているイベントを削除する
セレクタを指定している場合、イベントを削除するには選択要素とセレクタをイベント設置時と同じように指定する必要があります。
```javascript
$('body').on('click', 'button', () => { alert('hello world'); });
$('body').off('click', 'button');
```
> .on()によってイベントをバインドしたセレクタと同じセレクタを指定します。

そのため、ボタンタグに付与されているクラスやid属性を指定してもイベントを削除できません。

```javascript
// イベントを削除できない
$('body').on('click', 'button', () => { alert('hello world'); });
$('body').off('click', '#primary');
$('body').off('click', '#.js-click-here');
```
:::note info
セレクタを指定してイベントを設置した場合、削除時にも同じ選択要素とセレクタを指定する必要があります。
:::

## まとめ

jQueryでイベントを設置する際、セレクタの指定有無で変わること：

1. セレクタを指定すると、後から動的に生成された要素にもイベントを設置できる
2. セレクタを指定した場合、イベントはセレクタにマッチした要素で発生する

- イベントを設置する方法：

  1. 選択要素を直接参照する
  2. 選択要素を指定し、セレクタにマッチさせる

- イベントを削除する方法：

  1. 選択要素を直接参照した場合、タグ・クラス・ID属性で削除できる
  2. セレクタにマッチさせた場合、選択要素とセレクタを設置時と同じにすることで削除できる

動的に後から生成された要素にもイベントを設置したい場合は、セレクタにマッチさせる方法を使いましょう。

## 引用サイト
[.on() | jQuery 1.9 日本語リファレンス | js STUDIO](https://js.studio-kingdom.com/jquery/events/on)
[.off() | jQuery 1.9 日本語リファレンス | js STUDIO](https://js.studio-kingdom.com/jquery/events/off)