本人並不是專業的前端,只是因爲須要被迫轉作一段時間的前端,一段時間以來開始探索javascript上的MVC模式,最終打算從Backbone下手。在實戰了一段時間之後,對Backbone有了一些我的的理解,記錄在這裏。不過,MVC是講爛掉的話題了,本文並不討論。原文:Backbone精髓,觀察者模式和事件javascript
設計模式將人們在以往的開發過程當中的經驗加以總結,以指導後人。然而,本人從事web後端開發的幾年間,所使用到的設計模式其實很單一,無非就是工廠模式、單例模式、依賴反轉。而更多的模式已經被開發框架所實現,程序員要作到僅僅是寫幾個if-else
和for
以實現業務邏輯。那麼真正須要設計模式的地方在哪裏呢?翻遍設計模式的書,可發現其中的例子基本上是用戶界面實現、編譯器實現,不少高深的模式都在這些應用中得以體現。html
注意到如今web應用愈來愈多,而傳統的客戶端應用愈來愈少(除app以外),而人們對web程序的用戶體驗要求也是愈來愈高,傳統的表單提交、頁面刷新、重定向等用戶交互方式愈來愈不被用戶買帳。所以,javascript的歷史地位空前的高,而且,圍繞javascript,產生了大量的庫和框架方便基於瀏覽器開發用戶交互,甚至提出了javascript MVC思想,諸多的框架在javascript層面上實現了MVC模式。前端
其實,我的認爲UI交互邏輯最須要的是MV模式,即模型和視圖的關聯,至於控制器,無關緊要。而M和V之間的實現關聯的重要設計模式之一就是觀察者模式
,即因爲視圖呈現的複雜和多樣化,爲了便於擴展,須要視圖有一種隨模型數據的變化而「自行變化」的能力,而實現方式就是,視圖經過偵聽模型對象的變化而渲染本身,不須要外力來渲染,外力只須要改變惟一的標準--模型對象就能夠了。java
根據上面討論,要實現觀察者模式,事件
是很是重要的機制。在瀏覽器和javascript中,原生的事件是瀏覽器實現的基於DOM的事件體系。然而,這在咱們須要的M和V的觀察者模式中是不夠的。幸虧,Backbone實現了這樣的機制。有了它,可以讓任何javascript對象擁有「事件能力」,來看看是如何作到的:程序員
你可能沒有注意過Backbone.Events
就是事件實現的核心,它可讓對象擁有事件能力web
var Events = Backbone.Events = { .. }
那麼具體的看,事件能力究竟包含哪些能力呢?咱們簡單的來看一下:後端
使當前對象偵聽obj
對象的一個叫name
的事件,當事件被觸發後,回調callback
設計模式
使當前對象偵聽obj
對象的一個叫name
的事件,當事件被觸發後,回調callback
一次(之後不會在回調)數組
當前對象觸發name
事件瀏覽器
看下面的實驗下面的代碼:
var model = _.extend({},Backbone.Events); var view = _.extend({},Backbone.Events); view.listenTo(model,'custom_event',function(){ alert('catch the event') }); model.trigger('custom_event');
能夠在jsfiddle上實驗這個代碼,結果以下:
能夠看到,依靠Backbone.Events
是能夠實現觀察者模式的。由於對於上面代碼的model
對象而言,它並不知道view
對象在偵聽它,甚至能夠有更多的其餘對象去偵聽這個model。這樣的話,若是model發生了某種改變就能夠經過事件來發出通知。
可是,大量的將Backbone.Events
擴展到實際的對象上,顯然是一種內存浪費,那麼何不將它擴展到原型prototype
上呢?因而就有了Backbone的Model和View等核心類。例如Backbone.Model
:
var Events = Backbone.Events = { .. } var Model = Backbone.Model = function(attributes, options) { ... }; _.extend(Model.prototype, Events, { ... })
從上面的代碼能夠看出,Backbone核心的類只不過是將Backbone.Events
擴展到自身的prototype
上罷了,這樣全部基於Backbone核心類建立出來的對象就有了事件能力。
下面是一個體現觀察者模式的經典例子:
var Todo = Backbone.Model.extend({ model.trigger('destroy'); }); var TodoView = Backbone.View.extend({ events: { "click a.destroy" : "clear", }, initialize: function() { this.listenTo(this.model, 'destroy', this.remove); }, clear: function() { this.model.destroy(); }, remove: function() { this.$el.remove(); } });
上面的例子忽略了不少細枝末節,只是想說明一個界面元素的刪除動做,首先是刪除模型,模型隨後觸發刪除事件,因爲這個刪除事件,界面元素才被刪除
被偵聽的對象維護一個事件數組_event
,其餘對象在調用listenTo
時,會將事件名與回調維護到隊列中:
一個事件名能夠對應多個回調,對於被偵聽者而言,只知道回調的存在,並不知道具體是哪一個對象在偵聽它。
當被偵聽者調用trigger(name)
時,會遍歷_event
,選擇同名的事件,並將其下面全部的回調都執行一遍。
Backbone雖然是MVC模式的框架,可是其核心倒是UI界面的觀察者模式和事件機制。有了事件,並靈活運用觀察者模式,才能實現複雜界面的複雜邏輯。本文對此進行了闡述,若有不妥之處,請指正。