EventEmitter (EventDispacher) の階層構造

フロントエンドにおいて、それなりに普遍的な問題な気もするんだけど、
例えば、何かDOMと紐づくクラスを作ると、
どうしても親子関係を持たせたくなって

class ParentUnit extends EventEmitter
  constructor: ->
    @childUnit = new ChildUnit
  render: ->
    """<div>#{@childUnit.render()}</div>"""

class ChildUnit extends EventEmitter
  constructor: ->
  someHandler: (e) ->
    @emit "childevent", e
  render: ->
    "<p>child unit</p>"

parentUnit = new ParentUnit
parentUnit.on "childevent", -> # こうしたい

このとき、子から親にどうやってイベント(クリックとか)を伝えるかという問題に直面する。

1. バブリングさせる

class ParentUnit
  constructor: ->
    @childUnit = new ChildUnit
    @childUnit.on "childevent", @handlerChildEvent
  handlerChildEvent: (e) =>
    @emit "childevent", e

メリット

  • わかりやすい
  • 子が疎結合を維持できる
  • イベントを消したりまとめたり変形できる

デメリット

  • 階層が深くなるとめんどい
  • イベントを消したりまとめたり変形される

2. グローバルなEventEmitterを使う

globalEventEmitter = new EventEmitter
class ChildUnit
  someHandler: (e) ->
    globalEventEmitter.emit "childevent", e

メリット

デメリット

  • 良くない

3. 親を引き連れ回す

class ChildUnit
  constructor: (@parent) ->
  someHandler: (e) ->
    @parent.emit "childevent", e

メリット

  • イベントがそのまま届く

デメリット

  • 気をつけないと子が密結合っぽくなる
  • 似たようなことをするのに表現の仕方が多すぎる

4. EventEmitterをメンバとして持つ

parentEvent = new EventEmitter
class ParentUnit
  constructor: (@eventEmitter) ->
    @childUnit = new ChildUnit @eventEmitter
class ChildUnit
  constructor: (@eventEmitter) ->
  someHandler: (e) ->
    @eventEmitter.emit "childevent", e
parentUnit = new ParentUnit parentEvent
parentEvent.on "childevent", ->

メリット

  • イベント用のオブジェクトが独立できる

デメリット

  • あまり見ない
  • イベント用のオブジェクトが独立してる

5. そもそも親子関係を持たせない

メリット

  • 親も疎結合になる
  • 複雑な親子関係を組む時、見通しが良い

デメリット

  • めんどい

ちなみに eventemitter2名前空間を切れる