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

資訊專欄INFORMATION COLUMN

Backbone源碼解讀(二)

Sleepy / 2927人閱讀

摘要:以為例構(gòu)造函數(shù)的內(nèi)容構(gòu)造函數(shù)的內(nèi)部一般會(huì)做以下幾個(gè)操作各種給內(nèi)部對(duì)象設(shè)置屬性。為什么呢源碼做出了解釋。在里面會(huì)調(diào)用用戶傳入的回調(diào)函數(shù)并觸發(fā)事件表示已經(jīng)同步了。整個(gè)的源碼事實(shí)上就是這兩組東西。

1. 開場(chǎng)

強(qiáng)烈建議一邊看著源碼一邊讀本文章,本文不貼大段代碼。源碼地址。
在寫backbone應(yīng)用的時(shí)候,說實(shí)話,大部分的時(shí)間都是在寫這三個(gè)模塊的內(nèi)容。關(guān)于這三個(gè)模塊的分析網(wǎng)上隨隨便便就能找到一堆還不錯(cuò)的文章。但我希望能夠找到一條線索,能把各自模塊的內(nèi)部機(jī)理整理清楚。就像前一篇文章中介紹的Events那樣。Events整個(gè)模塊其實(shí)就是通過一些外部的方法來修改內(nèi)部對(duì)象的屬性,從而達(dá)到事件管理的目的。以一條線索來看待整個(gè)模塊,一切都清晰了然了。下面就開始了~

(最近要開學(xué),要準(zhǔn)備回學(xué)校上課,亂七八糟的東西很多,所以文章可能也會(huì)拖一陣子啦...但是我還是非常希望能夠?qū)懴聛?,半途而廢的感覺真心不好...

這一篇文章主要講backboneModel, CollectionView。這三個(gè)模塊有很多相似的地方。這篇文章不會(huì)把模塊的每一個(gè)方法都介紹一遍,因?yàn)橹灰丛创a就知道,其實(shí)主要的方法只有幾個(gè),而很多其他的模塊實(shí)際上只是在調(diào)用這幾個(gè)核心的方法而已。

2. Model & Collection & View

首先講一下三者的相似之處。這一節(jié)讓我們來看看這三個(gè)模塊一個(gè)總體結(jié)構(gòu)。
這三個(gè)模塊在結(jié)構(gòu)上和Events不同。他們先通過以下方式來定義構(gòu)造函數(shù)。(以View為例)

var View = Backbone.View = function(options) {
    // 構(gòu)造函數(shù)的內(nèi)容
};

構(gòu)造函數(shù)的內(nèi)部一般會(huì)做以下幾個(gè)操作:

各種給內(nèi)部對(duì)象設(shè)置屬性。(各種this.a = b

調(diào)用preinitialize

this.preinitialize.apply(this, arguments);

調(diào)用initialize

this.initialize.apply(this, arguments);

各個(gè)模塊的方法和屬性是通過underscoreextend來獲得的。注意在extend新加入的方法和屬性中,以下劃線開頭的變量是內(nèi)部函數(shù)名。(其實(shí)理論上用戶也可以調(diào)用這些方法,誰叫Javascript沒有內(nèi)部變量呢...)這些內(nèi)部方法是供自己模塊內(nèi)部調(diào)用的。

_.extend(View.prototype, Events, {
    // 這里是各種對(duì)View.prototype的拓展,定義各種方法
});

還有一個(gè)比較大的共同點(diǎn),就是slient參數(shù)。這個(gè)參數(shù)決定了是否要trigger一個(gè)事件,在源碼用占了很大的篇幅對(duì)其進(jìn)行分類討論。

3. Model 3.1 關(guān)鍵方法

有一些關(guān)鍵的方法一進(jìn)入函數(shù)就會(huì)根據(jù)傳入的參數(shù)的形態(tài)進(jìn)行變化。因?yàn)閎ackbone一些方法支持兩個(gè)參數(shù)傳入或者一個(gè)數(shù)組傳入,這時(shí)候需要有個(gè)判斷。

3.2 set

set方法在model里面是個(gè)很不好理解的東西,看了網(wǎng)上大多數(shù)解析感覺都很模糊(而且遇到難理解的就用一些借口蒙混過去)。不得不說set里面復(fù)雜精妙程度是每讀一遍驚嘆一遍。
我想以變量的角度來講解可能是一個(gè)比較好的角度。

changingthis._changing
如果這個(gè)函數(shù)只是從頭執(zhí)行到尾,那說實(shí)話,這兩個(gè)變量沒有任何意義。因?yàn)樗麄兊闹凳谴_定的??春瘮?shù)開頭:

var changing   = this._changing;
this._changing = true;

在函數(shù)結(jié)尾:

this._changing = false;

這個(gè)changing將永遠(yuǎn)永遠(yuǎn)是false。我上網(wǎng)看到有人說可能是webWorker,多線程相關(guān)的東西,但我直接在源碼console的時(shí)候卻發(fā)現(xiàn),這個(gè)changing是會(huì)變的,而且我用得是todo范例。todo范例沒有任何類似webWorker的東西。這個(gè)假設(shè)猜測(cè)應(yīng)該來說是不正確的。(不過這篇文章講得也很不錯(cuò)啊)
所以這個(gè)changing到底有什么用呢?答案就是遞歸函數(shù)。set里明明沒有遞歸???其實(shí)遞歸藏在了所有trigger的事件的回調(diào)函數(shù)里面。源代碼下面的這一段:

// You might be wondering why there"s a `while` loop here. Changes can
// be recursively nested within `"change"` events.
while (this._pending) {
    options = this._pending;
    this._pending = false;
    this.trigger("change", this, options);
}

這一個(gè)while里的trigger使得函數(shù)發(fā)生遞歸,然后重新調(diào)用set。這樣的話,下一次changing就等于true了,這個(gè)變量的作用才能發(fā)揮??梢钥匆幌逻@個(gè)鏈接里面的講解。

current變量是用來作為引用改變attributes的,其實(shí)是set能設(shè)置attributes的本質(zhì)。

changes數(shù)組是用來存放改變了的key的,用于后期的事件觸發(fā)。

changed & _previousAttributes
把這兩個(gè)放到一起是因?yàn)樗麄兊囊粋€(gè)特殊的地方。我在todo的主函數(shù)的render里面console,發(fā)現(xiàn)不論我做什么操作,changed === {},_previousAttributes沒有發(fā)生改變。后來在查看官方文檔的時(shí)候,才了解previous的用法:

var bill = new Backbone.Model({
  name: "Bill Smith"
});

bill.on("change:name", function(model, name) {
  alert("Changed name from " + bill.previous("name") + " to " + name);
});

bill.set({name : "Bill Jones"});

set方法在被調(diào)用的時(shí)候,previous只有在回調(diào)函數(shù)里才能有用,也就是說,在回調(diào)函數(shù)外面想要用這個(gè)previous獲取前一個(gè)值是不可能的。它只能獲取到當(dāng)前值。為什么呢?源碼做出了解釋。當(dāng)用戶做出操作需要用到set方法的時(shí)候,其實(shí)set方法并不是直接執(zhí)行完就結(jié)束了。在這個(gè)方法里面觸發(fā)了很多的事件,而previous只有在函數(shù)里觸發(fā)了的事件的回調(diào)函數(shù)“里面”才能返回正確的“前一個(gè)值”。changed也同理,因?yàn)椴徽撝虚g如何變化,遞歸,到最后它會(huì)被設(shè)置為{}。

3.3 save

save方法的作用是把當(dāng)前model的狀態(tài)保存到數(shù)據(jù)庫(kù)中,因此不可避免地要用到ajax。由于backbone已經(jīng)有了一個(gè)封裝好的方法sync用于觸發(fā)ajax,因此在save當(dāng)中重點(diǎn)是設(shè)置參數(shù)。需要設(shè)置的有successerror,method

success里面會(huì)調(diào)用用戶傳入的回調(diào)函數(shù)并觸發(fā)sync事件表示已經(jīng)同步了。

error用封裝好的wrapError函數(shù),這個(gè)函數(shù)用得很多,用于處理錯(cuò)誤。

method根據(jù)實(shí)際要用那種方法設(shè)置
其中比較值得注意的是wait參數(shù)。這個(gè)參數(shù)會(huì)影響頁面更新的時(shí)機(jī)。如果waittrue的話,就會(huì)需要等到服務(wù)器端相應(yīng)才更新頁面,否則就會(huì)立即更新。

3.4 destory

destory方法也是與ajax有密切聯(lián)系的。主要也是設(shè)置ajax參數(shù)。它分了幾種不同的情況并作出了相應(yīng)的處理:

waitfalse,不用等待。發(fā)起delete請(qǐng)求,觸發(fā)內(nèi)部函數(shù)destory

waittrue,發(fā)起ajax,等待服務(wù)器響應(yīng)才觸發(fā)destory更新頁面。

這是一個(gè)新的model,那就不需要發(fā)起請(qǐng)求了。

3.5 isValid

驗(yàn)證函數(shù),通過調(diào)用內(nèi)部函數(shù)_validate,在通過這個(gè)函數(shù)調(diào)用validate函數(shù)。然后返回一個(gè)錯(cuò)誤,如果沒有錯(cuò)誤就返回true,否則觸發(fā)invalid,返回false。

4. Collection

Collection類似一個(gè)數(shù)組,里面存放著各種以model為結(jié)構(gòu)的對(duì)象。在Collection中也有這形式的判斷,如果傳入的參數(shù)是單個(gè)對(duì)象就會(huì)被轉(zhuǎn)換成數(shù)組。

4.1 set

這是Collection的一個(gè)很常用的方法,源碼中這一段很長(zhǎng),也有點(diǎn)繁瑣,但是沒有特別難以理解的地方。整個(gè)set的結(jié)構(gòu)是:

設(shè)置幾個(gè)數(shù)組(下面會(huì)詳細(xì)講)

設(shè)置實(shí)際的models(修改this.models

trigger事件

主要來說就是有如下幾個(gè)關(guān)鍵點(diǎn):

如果不符合model形式,轉(zhuǎn)換之。

設(shè)置相應(yīng)的插入位置at

設(shè)置set數(shù)組。set數(shù)組在里面作用是為給后面排序做準(zhǔn)備。里面存放的是新的Collectionmodels。

設(shè)置toAdd數(shù)組。這個(gè)數(shù)組是用于存儲(chǔ)新建的合法的model,然后需要調(diào)用內(nèi)部函數(shù)_addReference設(shè)置索引于_byId數(shù)組,并且添加all事件(后面就可以通過model直接trigger事件)。當(dāng)slient不是true,后期可以通過遍歷它來觸發(fā)add事件。

設(shè)置toMerge數(shù)組。當(dāng)這個(gè)model是原本已經(jīng)存在的model的時(shí)候(cid匹配),就會(huì)修改,然后被push進(jìn)這個(gè)數(shù)組中。

設(shè)置toRemove數(shù)組。然后通過內(nèi)部函數(shù)_removeModels刪除那些已經(jīng)不在set里面的models。

修改this.models,分兩種情況,一種是直接整個(gè)替換掉,一種是后面再添加。

如果silent不是true就要觸發(fā)事件。特別值得注意的一點(diǎn)是:這里面的事件有兩種,一種事件是由Model發(fā)出的,一種事件是有Collection發(fā)出的。從Model發(fā)出的事件可以很容易_addReference函數(shù)中發(fā)現(xiàn)

model.on("all", this._onModelEvent, this); 

在這里注冊(cè)了,調(diào)用的是_onModelEvent函數(shù)。而其他沒有注冊(cè)的函數(shù)應(yīng)該是給使用者注冊(cè)監(jiān)聽用的。

4.2 sort

sort所依據(jù)的是用戶傳入的comparator參數(shù),這個(gè)參數(shù)可以是一個(gè)字符串也可以是一個(gè)函數(shù),如果是字符串就通過underscoresortBy方法,如果是個(gè)函數(shù)就直接傳入sort的第二個(gè)參數(shù)中。

4.3 fetch & create

fetchcreatebackbone與服務(wù)器端交互的一個(gè)接口。兩個(gè)方法內(nèi)部處理其實(shí)都很好理解,就是設(shè)置ajax參數(shù)。最終本質(zhì)上都是觸發(fā)sync。但是唯一不同的是fetch是通過自身的sync函數(shù),但create是通過調(diào)用modelsave,然后觸發(fā)sync的。在

model.save(null, options);

跟著這個(gè)save函數(shù)里面走,就會(huì)發(fā)現(xiàn)參數(shù)null傳入是有意義的。在save里面的參數(shù)設(shè)置會(huì)很好地賦值并最后觸發(fā)sync,而且有一個(gè)很有趣的點(diǎn),就是這個(gè)createmodel傳上服務(wù)器,但是這個(gè)model是一個(gè)相對(duì)獨(dú)立的狀態(tài),僅僅通過它的Collection屬性來維系和Collection的關(guān)系。那就要求后端需要把這一個(gè)model添加到相應(yīng)的Collection數(shù)據(jù)里面去。

4.4 reference

Collection有一個(gè)值得關(guān)注的內(nèi)部變量,那就是_byId,這個(gè)變量用cidid(所以model是一對(duì)一對(duì)出現(xiàn)的)來存儲(chǔ)Collection里面的model,方便直接性的存取。在源碼中有很多操作目的就是刪除,增加,獲取這個(gè)內(nèi)部變量的值。

4.5 CollectionIterator

這東西我覺得很有意思...在官方文檔里面沒有提到,但是由于涉及到ES6的東西所以覺得有點(diǎn)眼前一亮的感覺(哈哈哈),backbone在這里用了Symbol.iterator,具體用法在這個(gè)鏈接里有介紹,還是挺清晰的。通過設(shè)置CollectionIteratorSymbol.iteratornext方法。它通過內(nèi)部變量_kind來區(qū)分種類,_index來確定對(duì)應(yīng)的next的結(jié)果,這個(gè)對(duì)于寫迭代器還是有點(diǎn)借鑒意義的~

5. View

在寫backbone應(yīng)用的時(shí)候,View寫著寫著會(huì)越來越大...追根溯源,就是View的代碼很少...(大霧)。關(guān)于View,在寫相關(guān)代碼的時(shí)候有一些值是需要設(shè)置的(可選的)。下面的代碼就展示了可設(shè)置的參數(shù),這些參數(shù)在View的方法中會(huì)用到(如果有的話)。

var viewOptions = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"];

下面我會(huì)從兩個(gè)大的方面來解讀源碼,一個(gè)是element,一個(gè)是Events。整個(gè)View的源碼事實(shí)上就是這兩組東西。

5.1 Element

View字面意思是視圖,而在瀏覽器中,視圖就是html所呈現(xiàn)的頁面。每一個(gè)View事實(shí)上就對(duì)應(yīng)著html的一個(gè)元素(當(dāng)然這個(gè)元素里面可以有很多很多元素)。這個(gè)元素默認(rèn)標(biāo)簽是div。與元素相關(guān)的代碼其實(shí)很簡(jiǎn)單,首先要認(rèn)清this.elthis.$el。前者是真正的節(jié)點(diǎn),后者則是jquery對(duì)象的節(jié)點(diǎn)。后者由于是jquery式的,因此就可以做相關(guān)的jquery的操作。因此事件發(fā)起,刪除節(jié)點(diǎn),設(shè)置屬性的操作都是jqueryapi對(duì)this.$el或其子節(jié)點(diǎn)的操作。在進(jìn)入構(gòu)造函數(shù)的時(shí)候會(huì)調(diào)用一個(gè)叫_ensureElement的內(nèi)部函數(shù),在這個(gè)函數(shù)里會(huì)根據(jù)用戶設(shè)置的參數(shù)去構(gòu)建節(jié)點(diǎn),最后展現(xiàn)到頁面之上。

5.2 Events

事件是View中非常重要的組成。這是用戶可以操作數(shù)據(jù)的一個(gè)接口。在View里面和數(shù)據(jù)相關(guān)的方法有delegateEventsdelegates,undelegateEvents,undelegate。里面通過使用者設(shè)置的events屬性來創(chuàng)建各種事件,操作各種事件。

{
    "mousedown .title":  "edit",
    "click .button":     "save",
    "click .open":       function(e) { ... }
}

events相關(guān)代碼很簡(jiǎn)單,但是有一個(gè)非常非常巧妙的地方:就是作者用了jquery事件相關(guān)api命名空間。在delegate被調(diào)用的時(shí)候就給事件加上了一個(gè)特定的命名空間。

delegate: function(eventName, selector, listener) {
    this.$el.on(eventName + ".delegateEvents" + this.cid, selector, listener);
    return this;
}

因此在后續(xù)需要對(duì)整體的所有事件進(jìn)行操作的時(shí)候就會(huì)方便很多很多。

6. 最后的話

這次源碼解析不能百分百保證是正確的,有一些混雜了自己的思考。因?yàn)椴幌胂衿渌蟛糠值脑创a解析那樣,對(duì)于問題模糊處理。但我覺得還是有意義的,因?yàn)槊總€(gè)人讀的角度不一樣。兼聽則明,也希望讀者能夠包容,希望深刻理解backbone的讀者也請(qǐng)多讀幾篇文章,多讀幾遍源碼。下一篇文章要寫router & history,這一個(gè)模塊可以多帶帶拆出來作為SPA的一個(gè)入口,個(gè)人認(rèn)為這部分時(shí)backbonebackbone(骨架)。

希望能夠堅(jiān)持更下去吧,開學(xué)了,事情也開始多了起來...

本人還是backbone小白,如果哪里說錯(cuò)了或者怎樣,請(qǐng)輕噴~相互學(xué)習(xí)~

下面是全部的文章:

基于 Backbone + node 的個(gè)人簡(jiǎn)歷生成器(個(gè)人學(xué)習(xí)總結(jié))

Backbone源碼解讀(一)

Backbone源碼解讀(二)

Backbone源碼解讀(三)

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

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

相關(guān)文章

  • Backbone源碼解讀(三)

    摘要:事件關(guān)于路由觸發(fā)事件是通過兩個(gè)函數(shù)來完成的,它們分別是和前者會(huì)檢測(cè)路由是否發(fā)生了改變,如果改變了就會(huì)觸發(fā)函數(shù)并調(diào)用函數(shù),而后者會(huì)通過路由片段來找到相關(guān)的事件函數(shù)來觸發(fā)。 注意:強(qiáng)烈建議一邊閱讀源碼一邊閱讀本文。 終于到了backbone源碼解讀的最后一篇,這一篇和前面幾篇時(shí)間上有一定的間隔(因?yàn)橐貙W(xué)校有一堆亂七八糟的事...)。在這一篇里面會(huì)講解Bakcbone的sync & rou...

    feng409 評(píng)論0 收藏0
  • Backbone 源碼解讀(一)

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

    Kosmos 評(píng)論0 收藏0
  • 帶你讀Backbone源碼解讀之Events實(shí)現(xiàn)

    摘要:接受個(gè)參數(shù),包括事件的名稱,回調(diào)函數(shù)和回調(diào)函數(shù)執(zhí)行的上下文環(huán)境。保留回調(diào)函數(shù)在數(shù)組中取出對(duì)應(yīng)的以及中的函數(shù)。當(dāng)然,你同樣可以在綁定的回調(diào)函數(shù)執(zhí)行前手動(dòng)通過將其移除。 Backbone源碼解讀 Backbone在流行的前端框架中是最輕量級(jí)的一個(gè),全部代碼實(shí)現(xiàn)一共只有1831行1。從前端的入門再到Titanium,我雖然幾次和Backbone打交道但是卻對(duì)它的結(jié)構(gòu)知之甚少,也促成了我想讀...

    AndroidTraveler 評(píng)論0 收藏0
  • backbone源碼解讀

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

    Kross 評(píng)論0 收藏0
  • backbone源碼解讀

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

    wangxinarhat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<