Backbone精髓,觀察者模式和事件

前言

本人並不是專業的前端,只是因爲須要被迫轉作一段時間的前端,一段時間以來開始探索javascript上的MVC模式,最終打算從Backbone下手。在實戰了一段時間之後,對Backbone有了一些我的的理解,記錄在這裏。不過,MVC是講爛掉的話題了,本文並不討論。原文:Backbone精髓,觀察者模式和事件javascript

UI交互邏輯更須要設計模式

設計模式將人們在以往的開發過程當中的經驗加以總結,以指導後人。然而,本人從事web後端開發的幾年間,所使用到的設計模式其實很單一,無非就是工廠模式、單例模式、依賴反轉。而更多的模式已經被開發框架所實現,程序員要作到僅僅是寫幾個if-elsefor以實現業務邏輯。那麼真正須要設計模式的地方在哪裏呢?翻遍設計模式的書,可發現其中的例子基本上是用戶界面實現、編譯器實現,不少高深的模式都在這些應用中得以體現。html

注意到如今web應用愈來愈多,而傳統的客戶端應用愈來愈少(除app以外),而人們對web程序的用戶體驗要求也是愈來愈高,傳統的表單提交、頁面刷新、重定向等用戶交互方式愈來愈不被用戶買帳。所以,javascript的歷史地位空前的高,而且,圍繞javascript,產生了大量的庫和框架方便基於瀏覽器開發用戶交互,甚至提出了javascript MVC思想,諸多的框架在javascript層面上實現了MVC模式。前端

觀察者模式

其實,我的認爲UI交互邏輯最須要的是MV模式,即模型和視圖的關聯,至於控制器,無關緊要。而M和V之間的實現關聯的重要設計模式之一就是觀察者模式,即因爲視圖呈現的複雜和多樣化,爲了便於擴展,須要視圖有一種隨模型數據的變化而「自行變化」的能力,而實現方式就是,視圖經過偵聽模型對象的變化而渲染本身,不須要外力來渲染,外力只須要改變惟一的標準--模型對象就能夠了。java

Backbone的事件

根據上面討論,要實現觀察者模式,事件是很是重要的機制。在瀏覽器和javascript中,原生的事件是瀏覽器實現的基於DOM的事件體系。然而,這在咱們須要的M和V的觀察者模式中是不夠的。幸虧,Backbone實現了這樣的機制。有了它,可以讓任何javascript對象擁有「事件能力」,來看看是如何作到的:程序員

你可能沒有注意過Backbone.Events就是事件實現的核心,它可讓對象擁有事件能力web

var Events = Backbone.Events = { .. }

那麼具體的看,事件能力究竟包含哪些能力呢?咱們簡單的來看一下:後端

listenTo: function(obj, name, callback)

使當前對象偵聽obj對象的一個叫name的事件,當事件被觸發後,回調callback設計模式

listenToOnce: function(obj, name, callback)

使當前對象偵聽obj對象的一個叫name的事件,當事件被觸發後,回調callback一次(之後不會在回調)數組

trigger: function(name)

當前對象觸發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();
    }

});

上面的例子忽略了不少細枝末節,只是想說明一個界面元素的刪除動做,首先是刪除模型,模型隨後觸發刪除事件,因爲這個刪除事件,界面元素才被刪除

探究Backbone事件的實現原理

被偵聽的對象維護一個事件數組_event,其餘對象在調用listenTo時,會將事件名與回調維護到隊列中:

一個事件名能夠對應多個回調,對於被偵聽者而言,只知道回調的存在,並不知道具體是哪一個對象在偵聽它。

當被偵聽者調用trigger(name)時,會遍歷_event,選擇同名的事件,並將其下面全部的回調都執行一遍。

總結

Backbone雖然是MVC模式的框架,可是其核心倒是UI界面的觀察者模式和事件機制。有了事件,並靈活運用觀察者模式,才能實現複雜界面的複雜邏輯。本文對此進行了闡述,若有不妥之處,請指正。

相關文章
相關標籤/搜索