/ Famo.us

[Famo.us] Event 核心與模組介紹

[UPDATE] Famo.us 官方已捨棄此模組,詳情請看官方 Github

EventHandler, EventEmitter 這兩項核心很常出現在其他的模組當中,主要是負責事件控制、監聽與觸發,但是他跟 DOM 就沒有關係,單純的是綁在模組或是元件上面。


EventEmitter 核心

EventHandler 核心所依賴的核心(沒有之一,用於將事件往下擴散(或是將其子元件事件綁定在自己身上。

方法

  • emit(type, event) 觸發一個事件 type,並將該方法傳送到底下所屬的所有子處理程序
  • on(type, handler) 綁定一個事件,並指派一個子處理程序 handler
  • addListener 等同於 on
  • removeListener(type, handler) 移除一個事件,並且移除其子處理程序 handler
  • bindThis(owner) 指定自身的擁有者(通常為另一個物件或是模組

EventHandler 核心

依賴 EventEmitter 核心,做到更多事件控制的模組。他本身集合了事件與處理程序(callback)的分配,將二者放到陣列裡面互相對應,除了往下(downstream)傳遞之外,也能往上(upstream)監聽。

靜態方法

這兩項靜態方法,多是用於模組擴展時使用,目的是要讓你可以指派一個處理程序,讓他接收指定物件的事件觸發動作,或是接收指定物件的事件輸出。

  • EventHandler.setInputHandler 事件輸入(觸發
  • EventHandler.setOutputHandler 事件輸出(控制器輸出

方法

  • emit, triggerEventEmitteremit
  • on, addListenerEventEmitteron
  • pipe 將自身的事件指派給指定的物件
  • unpipe 取消上述指派
  • subscribe 監聽來自上層物件的事件
  • unsubscribe 取消上述監聽

EventHandler 補充

整個 Famo.us 所有的事件控制都由這兩個模組延伸出去,其中 EventHandler 占了大多數,這個模組有兩個靜態方法,個別都是一種混插(mixin)的方法,

  • setInputHandler 可接受 trigger, subscribe, 與 unsubscribe
  • setOutputHandler 可接受 pipe, unpipe, on, addListener, 與 removeListener

這兩個靜態方法多用於模組擴充上面,意即,當你自行開發的模組需要使用事件的時候,可以設定兩組參數來接收這兩個靜態方法。而這兩組方法可以將所有的事件綁定在你所指定的控制器身上(通常是自己。

Scrollview 為例,

this._eventInput = new EventHandler();
this._eventOutput = new EventHandler();

this._eventInput.pipe(this.sync);
this.sync.pipe(this._eventInput);

EventHandler.setInputHandler(this, this._eventInput);
EventHandler.setOutputHandler(this, this._eventOutput);

方法

  • emit, trigger 針對監聽者群觸發事件(包含自定事件
  • pipe, unpipe 針對監聽者群 A 發送(或取消)指定事件給 B 監聽者群
  • on, addListener 針對監聽者群註冊事件
  • subscribe, unsubscribe 針對監聽者群 A 訂閱(或取消)來自 B 監聽者群的指定事件

pipesubscribe 可以解釋為,

// 以下兩種寫法,結果相同
objectA.pipe(objectB);
objectB.subscribe(objectA);

EventEmitter 方法補充

  • emit 針對監聽者觸發事件
  • on, addListener 針對監聽者註冊事件
  • removeListener 針對監聽者移除事件

注意與 EventHandler 不同的地方,在於 EventHandler 是針對所有 同類型事件 的監聽者群去做動作,而 EventEmitter 只會針對 同類型事件 的單一監聽者做動作。兩者的面相並不太一樣,簡單來說,如果是以模組擴展為原則,那麼就是直接使用 EventHandler 就可以了。

至於 EventEmitter 能做什麼,只要是你模組當中,只需要單一事件操控(或者說不想讓整個事件對外擴散或是外部有權控制,那麼用 EventEmitter 也許就能符合你的需求。

Events 模組

  • EventMapper 將事件控制方法指派給所指定的方法
  • EventFilter 過濾事件控制方法與傳入資料,符合指定條件才會觸發事件
  • EventArbiter 設定事件控制器的模式

EventMapper

必須要傳入一個物件,這個物件需要擁有等同于 EventEmitter 或是 EventHandler 模組的條件,或是必須要有 emit 方法(此為必要條件之一

該模組的功能是,將所傳入的事件與其資料,透過所指定的物件,去觸發自定的事件控制器,舉個例子來說,當我觸發 click 的時候,我可以透過 EventMapper 將這個 click 事件,在物件中觸發,並去執行其他的程序。

有點類似於事件控制的路由器的角色。

EventFilter

必須要傳入一個條件程序,該條件程序必須返回 truefalse,用以過濾所傳入的事件是否允許被觸發,這個條件程序的寫法為,

var condition = function( type, data ) {
    var type = type; // 所傳入的事件,例如 click
    var data = data; // 所傳入的事件資料

    return true;
};

這個模組最主要是用於判別哪些事件,是否要在元件中被觸發。可以有效的控制透過 EventHandler 所傳來的事件,讓事件有執行與否的決定權。

EventArbiter

設定事件模式,這個模組有兩個特殊方法,

  • setMode 將事件派發指定為該模式
  • forMode 建立一個事件派發模式(或是返回該模式所屬的事件控制,如果該模式已存在

這個模組的功用,在於設定整個事件傳送過程中,事件被傳遞到哪一個位置上,所設計出來的。舉個簡易的例子來說,

var eventArbiter = new EventArbiter();

eventArbiter.forMode('start');
eventArbiter.forMode('step1');
eventArbiter.forMode('step2');
eventArbiter.forMode('end');

eventArbiter.setMode('start');

上述它會自動產生四個 EventHandler 的模組,分別在四種模式 start, step1, step2, 與 end,然後,我們將他設定在 start,則該模組(eventArbiter)會派發事件給所屬的 EventHandler,並且會觸發一個 change 事件,傳出 {from: startMode, to: mode} 這樣的資料。