自定義事件庫 EventFire
原始碼
EventFire倉庫地址: github.com/ccforward/E… (求點進去加個Star)
事件的管理主要有三點:繫結(on)、觸發(fire)、銷燬(off);所以寫一個自定義的事件庫就從這三點出發。
下面一步一步來寫
0、思考
繫結
就像在各種js庫裡面監聽DOM事件一樣,會有下面幾種方式:
event.on(`someEvent`, callback)
// 繫結多個事件
event.on([`someEventA`, `someEventB`], callback)
// 繫結一次
event.once(`someEvent`, callback)
// .... 其他複製程式碼
觸發
PS: 觸發的函式名可以是 trigger
或者 emmit
,個人感覺 fire
像遊戲一樣,聽起來更爽。
event.fire(`someEvent`)
// 觸發時繫結資料
event.fire(`someEvent`, {weapon: `machine gun`})
// 觸發多個事件
event.fire([`someEventA`, `someEventB`], callback)
// .... 其他複製程式碼
銷燬
銷燬肯定和事件繫結是對應關係
event.off(`someEvent`, callback)
event.off(`someEvent`)
event.off([`someEventA`, `someEventB`], callback)
// .... 其他複製程式碼
1、方法設計
一個簡單的事件庫應該有如下的方法:
on
事件繫結once
繫結一次off
事件解綁fire
觸發事件offAll
解綁所有事件listeners
返回某一事件上的監聽器enable
事件繫結和觸發-可用disable
事件繫結和觸發-暫停destory
解綁例項上的事件,並完全銷燬這個例項(不能再繼續繫結和觸發事件)
2、方法細節
on 方法
最開始時已經有了兩個基本的用法,思考後想到一些新的傳參方式來支援更加靈活的事件繫結:
- 字串引數,單個事件
on(`event`, callback, {once: true})
- 陣列引數,事件集合
on([`event1`, `event2`], callback, {once: true})
-
事件和回撥的鍵值對
on({ event1: function(){}, event2: function(){} }, {once: true});複製程式碼
-
繫結到所有事件上
on(function(){}, {once: true})複製程式碼
-
函式監聽器的名字也應該能支援正則
on(/^event/) on(/eventd+/)複製程式碼
最後一個可選引數是考慮到 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 方法
這兩個方法最開始考慮叫 pause
和 goon
但只是個構思,後來看了其他的事件庫後發現暫停繫結事件的執行是個很大的需求才改為更通用的名字
同樣這裡也需要引入一個內部變數 _enabled
來對應兩個方法設定為 true
和 false
destory 方法
這個方法實現起來最簡單粗暴,三步:
- offAll() 解綁
- 把所有內部變數設為
null
或false
- 上面所有方法設為空函式,也就是
Function.prototype
3、其他
作用域
函式在繫結的時候可以新增一個作用域,類似新增 {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 最後