摘要:用到了一個(gè)小技巧來防止誤傳入的覆蓋掉默認(rèn)的值。的精粹都在這個(gè)函數(shù)里面??吹竭@,給各種打補(bǔ)丁就有了可行性,支持就用,不支持的則降級(jí)到走的這種方式。
前言
都因?yàn)?IE8 不支持 Object.defineProperty,但是業(yè)務(wù)還不能脫離 IE7 和 IE8,故研究下 Backbone.Model 的實(shí)現(xiàn)機(jī)制,找機(jī)會(huì)給主流的 MVVM 框架補(bǔ)丁
偽代碼先來看看 Model 的構(gòu)造函數(shù)
var Model = Backbone.Model = function(attributes, options) { var attrs = attributes || {}; options || (options = {}); // 鉤子 this.preinitialize.apply(this, arguments); // 每個(gè)實(shí)例分配一個(gè)唯一的 cid this.cid = _.uniqueId(this.cidPrefix); // 數(shù)據(jù)對(duì)象 this.attributes = {}; // 不重要的內(nèi)容 if (options.collection) this.collection = options.collection; if (options.parse) attrs = this.parse(attrs, options) || {}; // 獲取預(yù)設(shè)在 defaults 字段中的初始鍵值對(duì)或匿名函數(shù) // 這里使用 _.result() 來兼容函數(shù)和對(duì)象兩種類型 var defaults = _.result(this, "defaults"); // 避免 attrs 中的 undefined 值覆蓋掉 defaults 中的默認(rèn)值 attrs = _.defaults(_.extend({}, defaults, attrs), defaults); // 初始化賦值 this.set(attrs, options); this.changed = {}; // 鉤子 this.initialize.apply(this, arguments); };
很簡(jiǎn)單的代碼,做了一些初始化賦值的事情。
用到了一個(gè)小技巧 attrs = _.defaults(_.extend({}, defaults, attrs), defaults); 來防止誤傳入的 undefined 覆蓋掉默認(rèn)的 defaults 值。
Backbone 的精粹都在 set(){} 這個(gè)函數(shù)里面。
set: function(key, val, options) { if (key == null) return this; // 統(tǒng)一 "key", "val" 和 {key:val} 這兩種形式 // attrs 最終為變動(dòng)的對(duì)象 var attrs; if (typeof key === "object") { attrs = key; options = val; } else { (attrs = {})[key] = val; } options || (options = {}); // 規(guī)則驗(yàn)證. if (!this._validate(attrs, options)) return false; var unset = options.unset; var silent = options.silent; var changes = []; var changing = this._changing; this._changing = true; // 預(yù)留上一次的值 if (!changing) { this._previousAttributes = _.clone(this.attributes); this.changed = {}; } // 備份一個(gè)當(dāng)前的數(shù)據(jù)對(duì)象 var current = this.attributes; var changed = this.changed; var prev = this._previousAttributes; // 遍歷傳入的新數(shù)據(jù)對(duì)象 for (var attr in attrs) { val = attrs[attr]; // 如果新數(shù)據(jù)與當(dāng)前不一致,則標(biāo)記變動(dòng)的鍵名 if (!_.isEqual(current[attr], val)) changes.push(attr); // 如果新數(shù)據(jù)與舊數(shù)據(jù)不一致,則更新已變動(dòng)的數(shù)據(jù)備份 if (!_.isEqual(prev[attr], val)) { changed[attr] = val; } else { delete changed[attr]; } // 真正干活的代碼,更新數(shù)據(jù)或者刪除數(shù)據(jù) unset ? delete current[attr] : current[attr] = val; } // 更新 id 字段 if (this.idAttribute in attrs) this.id = this.get(this.idAttribute); if (!silent) { if (changes.length) this._pending = options; // 遍歷變動(dòng)清單,并且逐個(gè)觸發(fā) `change:` 事件 for (var i = 0; i < changes.length; i++) { this.trigger("change:" + changes[i], this, current[changes[i]], options); } } if (changing) return this; if (!silent) { // 觸發(fā)一個(gè)總的 `change` 事件 // 注釋說這里用 while 是確保嵌套場(chǎng)景也只觸發(fā)一個(gè) `change` 事件 while (this._pending) { options = this._pending; this._pending = false; this.trigger("change", this, options); } } this._pending = false; this._changing = false; return this; },
整個(gè) set 里面,實(shí)際干活的就是 unset ? delete current[attr] : current[attr] = val; 。
沒看明白 this._changing 和 this._pending 的使用場(chǎng)景,感覺是一個(gè)當(dāng)多個(gè) set 同時(shí)執(zhí)行時(shí)候的一個(gè)標(biāo)記位,但是 JS 是單線程執(zhí)行,里面又都是 for 語(yǔ)句,按理說可以不用這兩個(gè)標(biāo)記位。又或者是我的理解有誤。
more看到這,給各種Observer打補(bǔ)丁就有了可行性,支持 Object.defineProperty 就用 Object.defineProperty,不支持的則降級(jí)到走 Backbone 的這種 for in 方式。
同步更新博客https://www.mxgw.info/a/backb...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81330.html
摘要:整個(gè)的代碼非常簡(jiǎn)潔,構(gòu)造邏輯也一目了然。生成唯一合并參數(shù)列表列表項(xiàng)目的初始化用戶定義的初始化事件處理可以看到,最重要的代碼,在于的初始化。這段代碼可以看出,如果實(shí)例化的時(shí)候有傳入一個(gè)節(jié)點(diǎn),則綁定這個(gè)節(jié)點(diǎn),否則生成一個(gè)這樣的節(jié)點(diǎn)。 整個(gè)View的代碼非常簡(jiǎn)潔,View構(gòu)造邏輯也一目了然。 javascriptvar View = Backbone.View = function(opt...
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...
摘要:因?yàn)槭且粭l數(shù)據(jù)記錄,也就是說,相當(dāng)于是一個(gè)數(shù)據(jù)集。通常我們需要重載函數(shù),聲明,以及通過或?yàn)橐晥D指定根元素。通過綁定視圖的函數(shù)到模型的事件模型數(shù)據(jù)會(huì)即時(shí)的顯示在中。實(shí)例屬性參數(shù)以及類屬性參數(shù)會(huì)被直接注冊(cè)到集合的構(gòu)造函數(shù)。 對(duì)于初學(xué)backbone.js的同學(xué)可以先參考我這篇文章:Backbone.js學(xué)習(xí)筆記(一) Backbone源碼結(jié)構(gòu) showImg(https://segme...
摘要:以為例構(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)上隨隨便便就能找到一堆...
摘要:個(gè)人認(rèn)為,讀懂老牌框架的源代碼比會(huì)用流行框架的要有用的多。另外,源代碼中所有的以開頭的方法,可以認(rèn)為是私有方法,是沒有必要直接使用的,也不建議用戶覆蓋。 寫在前面 backbone是我兩年多前入門前端的時(shí)候接觸到的第一個(gè)框架,當(dāng)初被backbone的強(qiáng)大功能所吸引(當(dāng)然的確比裸寫js要好得多),雖然現(xiàn)在backbone并不算最主流的前端框架了,但是,它里面大量設(shè)計(jì)模式的靈活運(yùn)用,以及令...
閱讀 1074·2021-11-12 10:34
閱讀 999·2021-09-30 09:56
閱讀 676·2019-08-30 15:54
閱讀 2610·2019-08-30 11:14
閱讀 1476·2019-08-29 16:44
閱讀 3215·2019-08-29 16:35
閱讀 2500·2019-08-29 16:22
閱讀 2453·2019-08-29 15:39