用观察者模式编写一个可被其他对象拓展复用自定义事件系统
觀察者模式
定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都將得到通知
什么是觀察者模式?
發布—訂閱模式又叫觀察者模式,它定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都將得到通知。在 JavaScript 開發中,我們一般用事件模型來替代傳統的發布—訂閱模式。
舉個栗子:
賣水果的張老板和王老板都要進一批香蕉,他們的水果都是在一個叫錢多多(下面統稱為錢老板)的水果批發商那里進的。當張老板和王老板到錢老板那里進水果的時候,錢老板告訴張老板和王老板,香蕉還沒有到貨,得過幾天才到貨。無奈之下,張老板和王老板都把他們的電話號碼留在了錢老板那里,囑咐錢老板,香蕉到貨后,第一時間通知他們。
上面錢老板就扮演了發布者的角色,張老板和王老板則扮演的是訂閱者角色。在香蕉到貨后,錢老板會主動給張老板和王老發消息,讓兩位老板來取香蕉。這樣的好處就是:香蕉沒到的這段時間,張老板和王老板可以做其他的事情,不用主動聯系錢老板,只需等待錢老板的消息即可。也就是程序代碼中的時間上解耦,對象間解耦。
自定義事件
其實觀察者模式我們都曾使用過,就是我們熟悉的事件
但是內置的事件很多時候不能滿足我們的要求
所以我們需要自定義事件
現在我們想實現這樣的功能 定義一個事件對象,它有以下功能
- 監聽事件(訂閱事件)
- 觸發事件(事件發布)
- 移除事件(取消訂閱事件)
當然我們不可能只訂閱一個事件,可能會有很多
所以我們要針對不同的事件設置不同的”鍵”
這樣我們儲存事件的結構應該是這樣的
代碼如下
var createEventSys = function(){return {// 通過on接口監聽事件eventName// 如果事件eventName被觸發,則執行callback回調函數on: function (eventName, callback) {//如果Event對象沒有handles屬性,則給Event對象定義屬性handles,初始值為{}//handles屬性是用來存儲事件和回調執行函數的(即存儲訂閱的事件和觸發事件后執行的相應函數方法)if(!this.handles){this.handles={};}//如果handles中不存在事件eventName,則將事件存儲在handles中,同時初始化該事件對應的回調邏輯函數集合if(!this.handles[eventName]){this.handles[eventName]=[];}//往handles中的eventName對應的回調邏輯函數集合push回調函數callbackthis.handles[eventName].push(callback);},// 觸發事件 eventNameemit: function (eventName) {//如果事件eventName有訂閱者,則依次執行事件eventName的訂閱者相應的回調方法if(this.handles[arguments[0]]){for(var i=0;i<this.handles[arguments[0]].length;i ){this.handles[arguments[0]][i](arguments[1]);}}},//移除事件 eventNameremove: function (eventName, fn) {//判斷事件eventName是否存在fn這個觀察者,如果有,則移除事件eventName的fn觀察者if(this.handles[eventName]){for(var i=0; i<this.handles[eventName].length; i ){if(this.handles[eventName][i] === fn){this.handles[eventName].splice(i,1);break;}}}}}; } var Event = createEventSys(); Event.on('test', function (result) {console.log(result); }); Event.on('test', function () {console.log('test'); }); Event.emit('test', 'hello world'); // 輸出 'hello world' 和 'test'//對象person1和對象person2拓展復用自定義系統 var person1 = {}; var person2 = {}; Object.assign(person1, createEventSys()); Object.assign(person2, createEventSys()); person1.on('call1', function () {console.log('person1'); }); person2.on('call2', function () {console.log('person2'); }); person1.emit('call1'); // 輸出 'person1' person1.emit('call2'); // 沒有輸出 person2.emit('call1'); // 沒有輸出 person2.emit('call2'); // 輸出 'person2'如上面代碼這樣,我們用觀察者模式就實現了一個基本完善的自定義事件系統。
總結
觀察者模式有兩個明顯的優點
時間上解耦
對象間解耦
在前端開發中,很多地方都適合用觀察者模式來做,在適當的地方善用觀察者模式
希望這篇文章對大家有幫助,喜歡的話,請關注我,我會持續更新一些技術文章到我的掘金主頁,謝謝大家支持!
更多專業前端知識,請上 【猿2048】www.mk2048.com
總結
以上是生活随笔為你收集整理的用观察者模式编写一个可被其他对象拓展复用自定义事件系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我理解中的“大前端”/“大无线”
- 下一篇: js操作table中tr的顺序,实现上移