1. このページの目的
カスタムイベントを使ってみる。
2. 基本事項
イベントリスナーの登録
elem.addEventListener('awesome', function (e) { /* ... */ }, false);
- この例の場合、ターゲットとなる要素に
'awesome'
という名前でイベントリスナーを登録している。 - 「この要素(elem)が
'awesome'
というイベントを持っている」わけではない。そうではなく、この要素に対してdispatchEvent()
が実行される際に、指定されたイベント名でイベントリスナーが登録されていれば、それらが実行されるだけある。
イベントの作成と発火
// イベントの作成
const eventAwesome = new CustomEvent(
// イベント名
'awesome',
// オプション
{
bubbles: true, // バブリングを許可
detail: { text: () => textarea.value } // データを保持させる
}
);
// イベントの発火
elem.dispatchEvent(event);
- この例の場合、ターゲットとなる要素に
'awesome'
という名前で紐付けられているイベントリスナーを実行させることになる。 - イベントリスナーが引数として受け取るのは、
dispatchEvent()
に渡したイベントオブジェクトである。 - Eventクラスを使ってもよいが、CustomEventクラスならデータの保持などができる。Event を拡張したクラスは、これ以外にもたくさんあり、それぞれ独自に必要なメソッドなどが追加されている。
- イベント名さえ同じにして「
new CustomeEvent()
➡dispatchEvent()
」すれば、何度でもその名前のイベントリスナーを実行させることができる。つまり、new CustomeEvent()
で生成したたった1つのオブジェクトを、毎回dispatchEvent()
に渡す必要はない。その都度イベントオブジェクト(イベント名は同じ)を作成して渡せば良い。
3. デモ
<!-- ここにカスタム要素を出力する -->
<input is="my-input1">
<script type="module">
// カスタム要素用クラスをインポートして、タグ名に紐付ける
import MyInput1 from './my-input1.js';
customElements.define('my-input1', MyInput1, {extends: 'input'});
const myInput1 = document.querySelector('input[is=my-input1]'),
demo1Output = document.querySelector('#demo1-output');
myInput1.addEventListener('keydown', function(e) {
demo1Output.textContent = '';
});
// カスタムイベントにリスナーを登録する
myInput1.addEventListener('b-input', function(e) {
demo1Output.textContent = `"b" が入力されました!(${e.detail})`;
});
</script>
export default class extends HTMLInputElement {
constructor() {
super();
this._onInput = this._onInput.bind(this);
this.addEventListener('input', this._onInput);
// カスタムイベントリスナーを登録する
this._onBInput = this._onBInput.bind(this);
this.addEventListener('b-input', this._onBInput, false);
}
disconnectedCallback() {
this.removeEventListerm('b-input', this._onBInput);
}
_onInput(e) {
const c = e.data;
if (c == 'b') {
// イベントを作成
const event = new CustomEvent('b-input', {
bubbles: true,
detail: 'イベントに保持された値' // object をセットすることも可能
});
// イベント発火!
this.dispatchEvent(event);
}
}
_onBInput(e) {
console.log(e);
}
};
以下の <input>
要素には、'b' が入力されたときだけ発火するイベントが設定してある。
4. メモ
- 1つのイベントに対する複数のリスナーの実行順序は指定できないっぽい。