寫一個簡單的支持Node.js&瀏覽器的自定義事件庫

原文地址git

自定義事件庫 EventFire

源碼

EventFire倉庫地址: github.com/ccforward/E… (求點進去加個Star)github

事件的管理主要有三點:綁定(on)、觸發(fire)、銷燬(off);因此寫一個自定義的事件庫就從這三點出發。數組

下面一步一步來寫函數

0、思考

綁定

就像在各類js庫裏面監聽DOM事件同樣,會有下面幾種方式:ui

event.on('someEvent', callback)
// 綁定多個事件
event.on(['someEventA', 'someEventB'], callback)
// 綁定一次
event.once('someEvent', callback)
// .... 其餘複製代碼

觸發

PS: 觸發的函數名能夠是 trigger 或者 emmit,我的感受 fire 像遊戲同樣,聽起來更爽。this

event.fire('someEvent')
// 觸發時綁定數據
event.fire('someEvent', {weapon: 'machine gun'})
// 觸發多個事件
event.fire(['someEventA', 'someEventB'], callback)

// .... 其餘複製代碼

銷燬

銷燬確定和事件綁定是對應關係spa

event.off('someEvent', callback)
event.off('someEvent')
event.off(['someEventA', 'someEventB'], callback)

// .... 其餘複製代碼

一、方法設計

一個簡單的事件庫應該有以下的方法:prototype

  • on 事件綁定
  • once 綁定一次
  • off 事件解綁
  • fire 觸發事件
  • offAll 解綁全部事件
  • listeners 返回某一事件上的監聽器
  • enable 事件綁定和觸發-可用
    disable 事件綁定和觸發-暫停
  • destory 解綁實例上的事件,並徹底銷燬這個實例(不能再繼續綁定和觸發事件)

二、方法細節

on 方法

最開始時已經有了兩個基本的用法,思考後想到一些新的傳參方式來支持更加靈活的事件綁定:設計

  • 字符串參數,單個事件
    on('event', callback, {once: true})
  • 數組參數,事件集合
    on(['event1', 'event2'], callback, {once: true})
  • 事件和回調的鍵值對code

    on({
      event1: function(){},
      event2: function(){}
    }, {once: true});複製代碼
  • 綁定到全部事件上

    on(function(){}, {once: true})複製代碼
  • 函數監聽器的名字也應該能支持正則

    on(/^event/)
    on(/event\d+/)複製代碼

最後一個可選參數是考慮到 once 方法後來添加的,對於 on 方法直接單次的事件綁定會更靈活些

on 最後還應該返回 this 來支持鏈式調用

once 方法

on 方法上添加了 {once: true} 這個可選參數後,這個方法就僅僅是 on 方法的一個變形了,再也不多說。

once 能夠和最後提到的 scope 統一放在配置項中

off 方法

off 很好理解, 它設計確定和 on 是對應的,不過會多一種調用方式:

off('eventName') 解綁 eventName 事件

fire 方法

fire 也是和 on 相對應的:

  • fire('event');
  • fire('event', data);
  • fire(['event1', 'event2']);
  • fire(['event1', 'event2'], data);
  • fire({event1: data, event2: data});

參數 data 能夠用在回調函數中,用來傳遞狀態、自定義數據等消息

offAll 方法

這裏須要建立三個內部變量,用來存儲回調函數,從而在解綁的時候可以找到已經綁定的函數

  • _handlers 存儲綁定的監聽器回調函數的鍵值對
  • _handlersAll 存儲綁定的在全部事件對象上的監聽器數組
    就是這種 on(function(){})
  • _handlersRegx 存儲經過正則方式綁定的監聽器以及正則pattern

因此解綁全部事件就是把上面三個變量置爲空

PS: 這個方法也可直接用在構造器中,初始化上面三個內部變量

listeners 方法

listeners(eventName) 返回一個綁定在 eventName 上的全部函數的數組

enable disabled 方法

這兩個方法最開始考慮叫 pausegoon 但只是個構思,後來看了其餘的事件庫後發現暫停綁定事件的執行是個很大的需求才改成更通用的名字

一樣這裏也須要引入一個內部變量 _enabled 來對應兩個方法設置爲 truefalse

destory 方法

這個方法實現起來最簡單粗暴,三步:

  1. offAll() 解綁
  2. 把全部內部變量設爲 nullfalse
  3. 上面全部方法設爲空函數,也就是 Function.prototype

三、其餘

做用域

函數在綁定的時候能夠添加一個做用域,相似添加 {once: true} 同樣, 添加一個名爲 scope 的配置來替代 this

on('event1', fn1, {scope: {hello: 'world'}})
on('event2', fn2, {scope: {hello: 'world'}, once: true})複製代碼

數據傳遞

fire 方法的最後一個參數 data, 可是在 fire 的時候須要傳遞數據,所以一個 data 變量就是個剛需了。

e.on('event', function(ev){
    console.log(ev.data)
});
e.fire('event', {a: 123});複製代碼

兼容性

最後添加 commonjs 和 AMD 規範的兼容,具體的代碼在 index.js 最後

相關文章
相關標籤/搜索