LoginSignup
19
20

More than 5 years have passed since last update.

カスタムイベントまとめ

Last updated at Posted at 2016-08-10

プリロード処理が完了したときにイベントを発行したいとかEVENT.COMPLETE
dom要素の高さが確定したときにイベントを発行したいとかEVENT.HEIGHT_FIXED
顔認識で対象を検出したときにイベントを発行したいとかEVENT.DETECTED
使い所の多いカスタムイベントのまとめ。
(イベント名は仮です)

EventEmitter

cdnで読み込む(node.jsなら不要)
https://cdnjs.com/libraries/EventEmitter

デモ:http://codepen.io/mo4_9/pen/ZOVEWW

<script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.1.0/EventEmitter.min.js"></script>
EventEmitter
var eventEmitter = new EventEmitter();
// 必ずしもEVENTオブジェクトをつくる必要はないが、
// カスタムイベントであることがわかりやすいのでオススメ
var EVENT = {
  DETECTED: 'detected',
  COMPLETE: 'complete'
};

// Listen for the event.
eventEmitter.on(EVENT.DETECTED, () => {
  console.log('DETECTED 発火!');
});
eventEmitter.on(EVENT.COMPLETE, () => {
  console.log('COMPLETE 発火!');
});

// Dispatch the event.
setTimeout(() => {
    eventEmitter.emit(EVENT.DETECTED);
}, 1000);
setTimeout(() => {
    eventEmitter.emit(EVENT.COMPLETE);
}, 3000);

応用例:【祝!リニューアル】カヤック 新コーポレートサイト、5種類テーマ切り替えの裏側!【フロントエンド芸】

こちらの応用例を元に書いた記事
http://qiita.com/mo4_9/items/4c12ad835b329ddc663c

JavaScript | dispatchEvent

DOMに紐づくEventDispatcher
var event = new Event('build');

// Listen for the event.
elem.addEventListener('build', function (e) { ... }, false);

// Dispatch the event.
elem.dispatchEvent(event);

以下の記事のようにクラス内部でイベントを発行して、外部に持ち出してあげるのが良い使い方。依存関係をなくせるのが利点。
javascriptでEventDispatcherを使うときのメモ

参考
Creating and triggering events

jQuery | trigger

DOMに紐付いていないEventDispatcher
const $dispatcher = $({});

// Listen
$dispatcher.on('complete', e => { ... });

// Dispatch
setTimeout( () => {
  $dispatcher.trigger('complete');
}, 1000);

使用例:プリロード
http://codepen.io/mo4_9/pen/VjqRqd

使用例:カウンターとポップアップ
http://codepen.io/mo4_9/pen/RREGwO

カウンターが7の倍数の時にポップアップを表示する。
カウンターとポップアップの機能は独立させたいので、別々にクラスをつくる。カウンターにDOMイベントを登録して、その中でポップアップのメソッドを実行する。

参考
jQuery初心者のためのJavaScript設計トレーニング 第1回 機能や役割に着目したコード整理

jQuery.callbacks()

DOMに紐付かないのに無駄にカスタムイベントを使ったり、Ajax通信でdone()やresolve()しか呼び出さないのに無駄にDeferredを使うくらいなら、jQuery.callbacks()を使ったほうがいいという認識が多い。
単純に任意のタイミングで関数を実行したいときに使える。オプション指定で実行制御も可能。

function hoge () {
  console.log("hoge");
}
function piyo () {
  console.log("piyo");
}

// コールバックオブジェクトを作成
const callbacks = $.Callbacks();
// コールバックに関数を登録
callbacks.add(hoge);
callbacks.add(piyo);
// 実行
callbacks.fire();
console.log
'hoge'
'piyo'

参考
https://api.jquery.com/jQuery.Callbacks/
http://www.jquerystudy.info/reference/callbacks/callbacks.html

Pub/Sub

デザパタ(オブザーバ)の一種Pub/Sub(パブリッシュ/サブスクライブ)
カスタムイベントの応用形みたいなニュアンス
上記のjQuery.callbacks()もPub/Subだし、大きく分けるとカスタムイベントもPub/Subに含まれるという考えもあるが、まあ実務で支障なく使えればいい。
フロントエンドjavascriptのpubsubパターンとカスタムイベントの違い・使い分け

pubsub-jsのサンプル

Topic1.js
import $ from 'jquery';
import PubSub from 'pubsub-js';

export default class Topic1 {

  constructor(opts = {}) {
    this.TOPIC_NAME = 'TOPIC1';
    this.init();
  }

  init() {
    const $btn1 = $('.btn').eq(0);
    $btn1.on('click', () => {
      // 発行
      PubSub.publish(`btnClick.${this.TOPIC_NAME}`, `hello world, ${this.TOPIC_NAME}`);
    })
  }

}
script.js
import PubSub from 'pubsub-js';
import Topic1 from './Topic1';

// 購読
PubSub.subscribe( 'btnClick.TOPIC1', mySubscriber );
function mySubscriber ( msg, data ) {
  console.log(`msg : ${msg}`, `data : ${data}`);
  // msg : btnClick.TOPIC1 data : hello world, TOPIC1
}

pubsub-jsをimportしておけば、別ファイルや別クラスの内部でもカスタムイベントを発行・購読できる。インスタンスを生成してtopic1.btnClick.TOPIC1みたいにしなくてよいので、慣れれば便利。

参考
javascriptで発行/購読パターンを使ってモジュールの関係を疎結合に保つ
【JSでデザインパターン】オブザーバ編

結論

個人的にはEventEmitterとjQueryのtriggerが使いやすくて好き。

自作もできるけど、ややこしくなるのでやめたほうがいい
シンプルな EventDispatcher つくりました

19
20
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
20