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

資訊專欄INFORMATION COLUMN

Backbone源碼研究 - Backbone.Model

Steve_Wang_ / 2749人閱讀

摘要:用到了一個(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._changingthis._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

相關(guān)文章

  • Backbone源碼研究 - Backbone.View

    摘要:整個(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...

    JellyBool 評(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.js學(xué)習(xí)筆記(二)細(xì)說MVC

    摘要:因?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...

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

    摘要:以為例構(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)上隨隨便便就能找到一堆...

    Sleepy 評(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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<