成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

帶你讀Backbone源碼解讀之Events實現(xiàn)

AndroidTraveler / 2916人閱讀

摘要:接受個參數(shù),包括事件的名稱,回調(diào)函數(shù)和回調(diào)函數(shù)執(zhí)行的上下文環(huán)境。保留回調(diào)函數(shù)在數(shù)組中取出對應(yīng)的以及中的函數(shù)。當(dāng)然,你同樣可以在綁定的回調(diào)函數(shù)執(zhí)行前手動通過將其移除。

Backbone源碼解讀

Backbone在流行的前端框架中是最輕量級的一個,全部代碼實現(xiàn)一共只有1831行1。從前端的入門再到Titanium,我雖然幾次和Backbone打交道但是卻對它的結(jié)構(gòu)知之甚少,也促成了我想讀它的代碼的原始動力。這個系列的文章主要目的是分享Backbone框架中可以用于日常開發(fā)的實踐參考,力求能夠簡明扼要的展現(xiàn)Backbone Modal, Controller和Sync這些核心內(nèi)容,希望能夠?qū)Υ蠹覍W(xué)習(xí)和使用Backbone有一些幫助。

這個系列的文章將包括以下3篇內(nèi)容:

Backbone源碼解讀之Events實現(xiàn)

Backbone源碼解讀之Router, History實現(xiàn)

Backbone源碼解讀之Model, Collection, Sync實現(xiàn)

本文是它的第一篇《Backbone源碼解讀之Events實現(xiàn)》

Backbone Events實現(xiàn)

Backbone的Event是整個框架運轉(zhuǎn)的齒輪。它的優(yōu)美之處在于它是Backbone的一個基礎(chǔ)方法,通過_.extend的方法Mixin到Backbone的每一個模塊中。

//Model
_.extend(Model.prototype, Events, {
    changed: null,

    //other Model prototype methods
    //...
}
Event的基礎(chǔ)概念

事件的管理是一個綁定在Events這個命名空間中的_events對象來實現(xiàn)的。
它的結(jié)構(gòu)是name: [callback functions]的key-callback_array鍵值對。

this._events = {
    change: [callback_on_change1, callback_on_change2, ....],
    ....
}

當(dāng)事件發(fā)生的時候,event從這個對象中根據(jù)事件的名稱取得回調(diào)函數(shù)數(shù)組,然后循環(huán)執(zhí)行每個回調(diào)函數(shù),也就說明了為什么多次綁定會重復(fù)觸發(fā)多次事件。

Event包括on, off, trigger三個基礎(chǔ)方法,其余的所有方法均是對它們的擴(kuò)展。

on(name, callback, context)

on接受3個參數(shù),包括事件的名稱,回調(diào)函數(shù)和回調(diào)函數(shù)執(zhí)行的上下文環(huán)境。其中context是可選參數(shù),如果你不是很熟悉JS的執(zhí)行上下文環(huán)境可以暫時不用管它。

拋開所有Backbone的花哨的檢查,執(zhí)行on的操作本質(zhì)就是向_events中name對應(yīng)的回調(diào)函數(shù)數(shù)組[callback functions]中Push新的函數(shù)。
簡單來說代碼實現(xiàn)就是這個樣子:

Events.on = function(name, callback, context) {
    if (callback) {
      var handlers = events[name] || (events[name] = []);
      handlers.push({callback: callback, context: context, ctx: context || this});
      }
      return this;
};

至于你在看源代碼的時候會長很多,那是因為一方面Backbone要處理關(guān)于_events以及_events[name]未初始化的兩種特殊情況。另一方面eventsApi,onApi這些方法是為了處理on時候你傳入的不是一個string類型的名稱和一個callback函數(shù)所做的條件處理。
例如下面兩種方法都是合法的:

//傳入一個名稱,回調(diào)函數(shù)的對象
model.on({ 
    "change": on_change_callback,
    "remove": on_remove_callback
});  

//使用空格分割的多個事件名稱綁定到同一個回調(diào)函數(shù)上
model.on("change remove", common_callback);  

但是核心其實都是同一個綁定函數(shù)。

值得注意的一點是由于Backbone接受all作為name的參數(shù),并且將回調(diào)函數(shù)保存在_events.all中,關(guān)于它的執(zhí)行詳細(xì)可以參考trigger。

off(name, callback, context)

與on不同,off的3個參數(shù)都是可選的。

如果沒有任何參數(shù)的時候,off相當(dāng)于把對應(yīng)的_events對象整體清空。

if (!name && !callback && !context) {
    this._events = void 0;
    return this;
}

如果有name參數(shù)但是沒有具體清除哪個callback的時候,則把_events[name]對應(yīng)的內(nèi)容全部清空。

if (!callback && !context) {
    delete this._events[name];
    continue;
}

如果還有進(jìn)一步詳細(xì)的callback和context的情況下,則進(jìn)入[callback functions]中進(jìn)行檢查,移除具體一個回調(diào)函數(shù)的條件非常嚴(yán)苛,必須要求上下文和函數(shù)與原來完全一致,也就是說如果傳入的callback或者context不是原有on對象的引用,而是復(fù)制的話,這里的off是無效的。

var remaining = [];
if(
    callback && callback !== handler.callback &&
    callback !== handler.callback._callback ||
    context && context !== handler.context
){
    //保留回調(diào)函數(shù)在數(shù)組中
}

trigger(name)

trigger取出name對應(yīng)的_events[name]以及_event.all中的callback函數(shù)。
需要注意的一點是,觸發(fā)對應(yīng)名稱的callback和all的callback使用了不一樣的參數(shù),all的參數(shù)中還包含了當(dāng)前事件的名稱。

//當(dāng)綁定3個以下回調(diào)函數(shù)的時候Backbone會做如下優(yōu)化處理,據(jù)說這樣是可以提高執(zhí)行效率的。    
var triggerEvents = function(events, args) {
    var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
    switch (args.length) {
      case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
      case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
      case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
      case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
      default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
    }
};
最簡單的Backbone事件使用

從使用上來講,對一個對象進(jìn)行事件的on綁定。然后在同一個對象的其他函數(shù)執(zhí)行過程中,或者其他的對象中,觸發(fā)該對象的trigger方法和對應(yīng)的事件名稱來執(zhí)行其上綁定的callback函數(shù)。

其他輔助函數(shù)

接下來再看看Event中進(jìn)一步定義了哪些其他輔助函數(shù)

once(name, callback, context)

效果相同與on,不過對應(yīng)的callback函數(shù)僅執(zhí)行一次。當(dāng)然,你同樣可以在once綁定的回調(diào)函數(shù)執(zhí)行前手動通過off將其移除。

來看看Once的實現(xiàn),由于添加了執(zhí)行過程中的移除方法,once在實際實行on的時候使用了如下匿名函數(shù):

var once = _.once(function() {function(){
    self.off(name, once);
    callback.apply(this, arguments);
});
return this.on(name, once, context);

但是細(xì)心的你一定發(fā)現(xiàn),保存在_event數(shù)組中的函數(shù)是once這個匿名函數(shù)了。但是用戶并不知道Backbone的這些操作,在取消綁定時仍然會使用原來的回調(diào)函數(shù)來試圖解除綁定。上面我們也提到,必須使用完全一致的函數(shù)才能夠取消綁定,那么為什么還能夠成功呢?

這里Backbone做了一個小小的操作,不知道你有沒有注意到上面off函數(shù)中有這樣一行內(nèi)容?

callback !== handler.callback._callback

既然callback是我們傳入的回調(diào)函數(shù),那么哪里來的_callback這個屬性呢?答案就在once里面。

var once = _.once(function() {...取消綁定,執(zhí)行callback);
once._callback = callback;

也就是Backbone在返回之前悄悄的為once這個函數(shù)添加了一個_callback的屬性,用來保存原來的回調(diào)函數(shù),這樣用戶在傳入原來的回調(diào)函數(shù)取消綁定的時候,off會檢查函數(shù)時候有_callback這個屬性和用戶傳入的函數(shù)匹配,同樣可以取消綁定。

listenTo(obj, name, callback)、listenToOnce(obj, name, callback)和stopListening(obj, name, callback)

除了將對象本身expose給另一個對象,讓另一個對象執(zhí)行trigger方法觸發(fā)該對象上綁定的event以外。Event還進(jìn)一步提供了listenTo系列的方法,執(zhí)行邏輯正好與on相反。
例如有如下要求,當(dāng)B對象上發(fā)生事件b的時候,觸發(fā)A對象的callbackOnBEvent函數(shù)。

// 使用on的情況下
B.on(“b”, A.callbackOnBEvent)

// 使用listenTo的情況下
A.listenTo(B, “b”, callbackOnEvent);

從實現(xiàn)上看,它門的區(qū)別就在于誰負(fù)責(zé)管理這個事件。第一個模型中,B就像是整個系統(tǒng)的master,負(fù)責(zé)事件到達(dá)的時候的分發(fā),讓不同的對象(如A)執(zhí)行對應(yīng)的方法。第二個模型中,B更像是一個信息棧,A監(jiān)聽B上發(fā)生的事件,并且在對應(yīng)事件到達(dá)的時候觸發(fā)自身相應(yīng)的回調(diào)函數(shù)。兩者并無好壞之分,但是從系統(tǒng)架構(gòu)上來說因為本身回調(diào)函數(shù)的上下文環(huán)境就是A,所以listenTo的方式可能會來的更加自然,而且由A自己來控制什么時候移除回調(diào)的執(zhí)行,也可以讓代碼的解耦程度更高。

超越Backbone

使用Event方法來處理異步請求讓代碼的可讀性大大增加。如果你的單頁面應(yīng)用恰好使用了Backbone作為前端框架,將Event通過Backbone.Events這個變量暴露出來,你可以使用類似Model擴(kuò)展的方法

//Your object
_.extend(your_object.prototype, Backbone.Events, {
    //other prototype methods
    //...
}

這樣你的Object也就具有了彼此綁定事件、觸發(fā)事件的能力。

即便你的前端并沒有使用Backbone,由于Events并不依賴Backbone的其他部分實現(xiàn),你完全可以將它放到自己的代碼lib中,作為一個基礎(chǔ)方法來使用。

類似的方式你也可以經(jīng)常在Node的后端看到

var util = require("util");
var events = require("events");

function MyStream() {
    events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);

總之,我個人是非常推薦多多使用Event來替代層級的Callback結(jié)構(gòu)。

根據(jù)2015年4月 穩(wěn)定版本Backbone.js 1.1.2的注釋版本。Master上的代碼和注釋版本稍有出入,哪位大神知道為什么嗎????

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85600.html

相關(guān)文章

  • Backbone 源碼解讀(一)

    1. 開場 1.1 MVC? MVC是一種GUI軟件的一種架構(gòu)模式。它的目的是將軟件的數(shù)據(jù)層(Model)和視圖(view)分開。Model連接數(shù)據(jù)庫,實現(xiàn)數(shù)據(jù)的交互。用戶不能直接和數(shù)據(jù)打交道,而是需要通過操作視圖,然后通過controller對事件作出響應(yīng),最后才得以改變數(shù)據(jù)。最后數(shù)據(jù)改變,通過觀察者模式更新view。(所以在這里需要用到設(shè)計模式中的觀察者模式) 1.2 Smalltalk-80...

    Kosmos 評論0 收藏0
  • Backbone源碼解讀(二)

    摘要:以為例構(gòu)造函數(shù)的內(nèi)容構(gòu)造函數(shù)的內(nèi)部一般會做以下幾個操作各種給內(nèi)部對象設(shè)置屬性。為什么呢源碼做出了解釋。在里面會調(diào)用用戶傳入的回調(diào)函數(shù)并觸發(fā)事件表示已經(jīng)同步了。整個的源碼事實上就是這兩組東西。 1. 開場 強(qiáng)烈建議一邊看著源碼一邊讀本文章,本文不貼大段代碼。源碼地址。在寫backbone應(yīng)用的時候,說實話,大部分的時間都是在寫這三個模塊的內(nèi)容。關(guān)于這三個模塊的分析網(wǎng)上隨隨便便就能找到一堆...

    Sleepy 評論0 收藏0
  • backbone源碼解讀

    摘要:個人認(rèn)為,讀懂老牌框架的源代碼比會用流行框架的要有用的多。另外,源代碼中所有的以開頭的方法,可以認(rèn)為是私有方法,是沒有必要直接使用的,也不建議用戶覆蓋。 寫在前面 backbone是我兩年多前入門前端的時候接觸到的第一個框架,當(dāng)初被backbone的強(qiáng)大功能所吸引(當(dāng)然的確比裸寫js要好得多),雖然現(xiàn)在backbone并不算最主流的前端框架了,但是,它里面大量設(shè)計模式的靈活運用,以及令...

    Kross 評論0 收藏0
  • backbone源碼解讀

    摘要:個人認(rèn)為,讀懂老牌框架的源代碼比會用流行框架的要有用的多。另外,源代碼中所有的以開頭的方法,可以認(rèn)為是私有方法,是沒有必要直接使用的,也不建議用戶覆蓋。 寫在前面 backbone是我兩年多前入門前端的時候接觸到的第一個框架,當(dāng)初被backbone的強(qiáng)大功能所吸引(當(dāng)然的確比裸寫js要好得多),雖然現(xiàn)在backbone并不算最主流的前端框架了,但是,它里面大量設(shè)計模式的靈活運用,以及令...

    wangxinarhat 評論0 收藏0
  • Backbone.js 源碼閱讀

    摘要:最近對主要對源碼進(jìn)行了閱讀,分別解讀了,,目錄如下希望大家能互相交流 最近對backbone主要對源碼進(jìn)行了閱讀,分別解讀了Backbone.Model,Backbone.View , Backbone.Collection,Backbone.Event,目錄如下: Backbone.View Backbone.Collection Backbone.Model Backbone....

    zlyBear 評論0 收藏0

發(fā)表評論

0條評論

AndroidTraveler

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<