国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Backbone源碼解讀(二)

Sleepy / 2924人閱讀

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

1. 開場

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

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

這一篇文章主要講backboneModel, CollectionView。這三個模塊有很多相似的地方。這篇文章不會把模塊的每一個方法都介紹一遍,因為只要看源碼就知道,其實主要的方法只有幾個,而很多其他的模塊實際上只是在調(diào)用這幾個核心的方法而已。

2. Model & Collection & View

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

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

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

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

調(diào)用preinitialize

this.preinitialize.apply(this, arguments);

調(diào)用initialize

this.initialize.apply(this, arguments);

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

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

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

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

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

3.2 set

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

changingthis._changing
如果這個函數(shù)只是從頭執(zhí)行到尾,那說實話,這兩個變量沒有任何意義。因為他們的值是確定的??春瘮?shù)開頭:

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

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

this._changing = false;

這個changing將永遠(yuǎn)永遠(yuǎn)是false。我上網(wǎng)看到有人說可能是webWorker,多線程相關(guān)的東西,但我直接在源碼console的時候卻發(fā)現(xiàn),這個changing是會變的,而且我用得是todo范例。todo范例沒有任何類似webWorker的東西。這個假設(shè)猜測應(yīng)該來說是不正確的。(不過這篇文章講得也很不錯?。?br>所以這個changing到底有什么用呢?答案就是遞歸函數(shù)set里明明沒有遞歸啊?其實遞歸藏在了所有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);
}

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

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

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

changed & _previousAttributes
把這兩個放到一起是因為他們的一個特殊的地方。我在todo的主函數(shù)的render里面console,發(fā)現(xiàn)不論我做什么操作,changed === {},_previousAttributes沒有發(fā)生改變。后來在查看官方文檔的時候,才了解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)用的時候,previous只有在回調(diào)函數(shù)里才能有用,也就是說,在回調(diào)函數(shù)外面想要用這個previous獲取前一個值是不可能的。它只能獲取到當(dāng)前值。為什么呢?源碼做出了解釋。當(dāng)用戶做出操作需要用到set方法的時候,其實set方法并不是直接執(zhí)行完就結(jié)束了。在這個方法里面觸發(fā)了很多的事件,而previous只有在函數(shù)里觸發(fā)了的事件的回調(diào)函數(shù)“里面”才能返回正確的“前一個值”。changed也同理,因為不論中間如何變化,遞歸,到最后它會被設(shè)置為{}。

3.3 save

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

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

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

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

3.4 destory

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

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

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

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

3.5 isValid

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

4. Collection

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

4.1 set

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

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

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

trigger事件

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

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

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

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

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

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

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

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

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

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

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

4.2 sort

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

4.3 fetch & create

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

model.save(null, options);

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

4.4 reference

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

4.5 CollectionIterator

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

5. View

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

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

下面我會從兩個大的方面來解讀源碼,一個是element,一個是Events。整個View的源碼事實上就是這兩組東西。

5.1 Element

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

5.2 Events

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

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

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

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

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

6. 最后的話

這次源碼解析不能百分百保證是正確的,有一些混雜了自己的思考。因為不想像其他大部分的源碼解析那樣,對于問題模糊處理。但我覺得還是有意義的,因為每個人讀的角度不一樣。兼聽則明,也希望讀者能夠包容,希望深刻理解backbone的讀者也請多讀幾篇文章,多讀幾遍源碼。下一篇文章要寫router & history,這一個模塊可以多帶帶拆出來作為SPA的一個入口,個人認(rèn)為這部分時backbonebackbone(骨架)。

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

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

下面是全部的文章:

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

Backbone源碼解讀(一)

Backbone源碼解讀(二)

Backbone源碼解讀(三)

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87893.html

相關(guān)文章

  • Backbone源碼解讀(三)

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

    feng409 評論0 收藏0
  • 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源碼解讀之Events實現(xiàn)

    摘要:接受個參數(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)知之甚少,也促成了我想讀...

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

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

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

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

    wangxinarhat 評論0 收藏0

發(fā)表評論

0條評論

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