cvm

          ;(function(exports) {
              var slice = Array.prototype.slice;
              var splice = Array.prototype.splice;
              var eventSplitter = /\s+/;
              var Events = {
                  on : function(events, callback, context) {
                      var calls, event, node, tail, list;
                      if(!callback)
                          return this;
                      events = events.split(eventSplitter);
                      calls = this._callbacks || (this._callbacks = {});
                      while( event = events.shift()) {
                          list = calls[event];
                          node = list ? list.tail : {};
                          node.next = tail = {};
                          node.context = context;
                          node.callback = callback;
                          calls[event] = {
                              tail : tail,
                              next : list ? list.next : node
                          };
                      }
                      return this;
                  },
                  off : function(events, callback, context) {
                      var event, calls, node, tail, cb, ctx;
                      if(!( calls = this._callbacks))
                          return;
                      if(!(events || callback || context)) {
                          delete this._callbacks;
                          return this;
                      }
                      events = events ? events.split(eventSplitter) : _.keys(calls);

                      while( event = events.shift()) {
                          node = calls[event];
                          delete calls[event];
                          if(!node || !(callback || context))
                              continue;
                          tail = node.tail;
                          while(( node = node.next) !== tail) {
                              cb = node.callback;
                              ctx = node.context;
                              if((callback && cb !== callback) || (context && ctx !== context)) {
                                  this.on(event, cb, ctx);
                              }
                          }
                      }

                      return this;
                  },
                  trigger : function(events) {
                      var event, node, calls, tail, args, all, rest;
                      if(!( calls = this._callbacks))
                          return this;
                      all = calls.all;
                      events = events.split(eventSplitter);
                      rest = slice.call(arguments, 1);
                      while( event = events.shift()) {
                          if( node = calls[event]) {
                              tail = node.tail;
                              while(( node = node.next) !== tail) {
                                  node.callback.apply(node.context || this, rest);
                              }
                          }
                          if( node = all) {
                              tail = node.tail;
                              args = [event].concat(rest);
                              // 遍歷并執行"all"事件中的回調函數列表
                              while(( node = node.next) !== tail) {
                                  node.callback.apply(node.context || this, args);
                              }
                          }
                      }

                      return this;
                  }
              };
              Events.bind = Events.on;
              Events.unbind = Events.off;
              
              var viewOptions = ['model','el', 'id', 'attributes', 'name']; //揀選錄入this的屬性
              var View = function(options){
                  this.cid = _.uniqueId('view');            
                  this._configure(options || {});        
                  this.initialize.apply(this, arguments); //調子類方法
              }
              _.extend(View.prototype, Events, {
                  _configure : function(options) {
                      if(this.options)
                          options = _.extend({}, this.options, options);
                      for(var i = 0, l = viewOptions.length; i < l; i++) {
                          var attr = viewOptions[i];
                          if(options[attr])
                              this[attr] = options[attr];
                      }
                      this.options = options;
                  },
                  // initialization logic.
                  initialize : function() {
                  },
                  render : function() {
                      return this;
                  },
                  remove : function() {
                      this.el.remove();
                      return this;
                  },
                  getElement : function(privateElKey) {
                      if(!privateElKey){
                          return this.el;
                      }
                      return this[privateElKey];
                  },
                  hideBar : function(elementsKey, show) {
                      var i=0, len=elementsKey.length;
                      if(show){
                          for(i=0; i<len; i++){
                              this[elementsKey[i]].show();
                          }
                      }else{
                          for(i=0; i<len; i++){
                              this[elementsKey[i]].hide();
                          }
                      }
                  }
              });
              var Model = function(attributes, options){
                  // defaults變量用于存儲模型的默認數據
                  var defaults;
                  // 如果沒有指定attributes參數, 則設置attributes為空對象
                  attributes || ( attributes = {});
                  if(options && options.parse)
                      attributes = this.parse(attributes);
                  if( defaults = getValue(this, 'defaults')) {
                      // 如果Model在定義時設置了defaults默認數據, 則初始化數據使用defaults與attributes參數合并后的數據(attributes中的數據會覆蓋defaults中的同名數據)
                      attributes = _.extend({}, defaults, attributes);
                  }
                  // attributes屬性存儲了當前模型的JSON對象化數據, 創建模型時默認為空
                  this.attributes = {};
                  // 定義_escapedAttributes緩存對象, 它將緩存通過escape方法處理過的數據
                  this._escapedAttributes = {};
                  // 為每一個模型配置一個唯一標識
                  this.cid = _.uniqueId('c');
                  this.changed = {};
                  this._silent = {};
                  this._pending = {};
                  //
                  this.set(attributes, {
                      silent : true
                  });
                  // Reset change tracking.
                  this.changed = {};
                  this._silent = {};
                  this._pending = {};
                  this._previousAttributes = _.clone(this.attributes);
                  this.initialize.apply(this, arguments);
              }
              _.extend(Model.prototype, Events, {
                  idAttribute : 'id',
                  initialize : function() {
                  },
                  // 根據attr屬性名, 獲取模型中的數據值
                  get : function(attr) {
                      return this.attributes[attr];
                  },
                   // 設置模型中的數據, 如果key值不存在, 則作為新的屬性添加到模型, 如果key值已經存在, 則修改為新的值
                  set : function(key, value, options) {
                      // attrs變量中記錄需要設置的數據對象
                      var attrs, attr, val;
                      // 參數形式允許key-value對象形式, 或通過key, value兩個參數進行單獨設置
                      // 如果key是一個對象, 則認定為使用對象形式設置, 第二個參數將被視為options參數
                      if(_.isObject(key) || key == null) {
                          attrs = key;
                          options = value;
                      } else {
                          // 通過key, value兩個參數單獨設置, 將數據放到attrs對象中方便統一處理
                          attrs = {};
                          attrs[key] = value;
                      }
                      // options配置項必須是一個對象, 如果沒有設置options則默認值為一個空對象
                      options || ( options = {});
                      // 沒有設置參數時不執行任何動作
                      if(!attrs)
                          return this;

                      // Check for changes of `id`.
                      if(this.idAttribute in attrs)
                          this.id = attrs[this.idAttribute];

                      var changes = options.changes = {};
                      // now記錄當前模型中的數據對象
                      var now = this.attributes;
                      // escaped記錄當前模型中通過escape緩存過的數據
                      var escaped = this._escapedAttributes;
                      var prev = this._previousAttributes || {};

                      // For each `set` attribute...
                      // 遍歷需要設置的數據對象
                      for(attr in attrs) {
                          // attr存儲當前屬性名稱, val存儲當前屬性的值
                          val = attrs[attr];

                          // 如果當前數據在模型中不存在, 或已經發生變化, 或在options中指定了unset屬性刪除, 則刪除該數據被換存在_escapedAttributes中的數據
                          // 以下代碼僅刪除通過escape緩存過的數據, 這是為了保證緩存中的數據與模型中的真實數據保持同步
                          if(!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {
                              delete escaped[attr];
                              (options.silent ? this._silent : changes)[attr] = true;
                          }

                          // 如果在options中設置了unset, 則從模型中刪除該數據(包括key)
                          // 如果沒有指定unset屬性, 則認為將新增或修改數據, 向模型的數據對象中加入新的數據
                          options.unset ?
                          delete now[attr] : now[attr] = val;
                          
                          if(!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
                              this.changed[attr] = val;
                              if(!options.silent)
                                  this._pending[attr] = true;
                          } else {
                              delete this.changed[attr];
                              delete this._pending[attr];
                          }
                      }

                      if(!options.silent)
                          this.change(options);
                      return this;
                  },
                  unset : function(attr, options) {
                      (options || ( options = {})).unset = true;
                      return this.set(attr, null, options);
                  },
                  change : function(options) {
                      options || ( options = {});
                      var changing = this._changing;
                      this._changing = true;

                      // Silent changes become pending changes.
                      for(var attr in this._silent)
                      this._pending[attr] = true;

                      // Silent changes are triggered.
                      var changes = _.extend({}, options.changes, this._silent);
                      this._silent = {};
                      for(var attr in changes) {
                          this.trigger('change:' + attr, this, this.get(attr), options);
                      }
                      if(changing)
                          return this;

                      // Continue firing `"change"` events while there are pending changes.
                      while(!_.isEmpty(this._pending)) {
                          this._pending = {};
                          this.trigger('change', this, options);
                          // Pending and silent changes still remain.
                          for(var attr in this.changed) {
                              if(this._pending[attr] || this._silent[attr])
                                  continue;
                              delete this.changed[attr];
                          }
                          this._previousAttributes = _.clone(this.attributes);
                      }

                      this._changing = false;
                      return this;
                  }
              });
              // ctor是一個共享的空函數, 用于在調用inherits方法實現繼承時, 承載父類的原型鏈以便設置到子類原型中
              var ctor = function() {
              };
              var inherits = function(parent, protoProps, staticProps) {
                  var child;
                  if(protoProps && protoProps.hasOwnProperty('constructor')) {
                      child = protoProps.constructor;
                  } else {
                      child = function() {
                          parent.apply(this, arguments);
                      };
                  }
                  _.extend(child, parent);
                  ctor.prototype = parent.prototype;
                  child.prototype = new ctor();
                  if(protoProps)
                      _.extend(child.prototype, protoProps);
                  if(staticProps)
                      _.extend(child, staticProps);
                  child.prototype.constructor = child;
                  child.__super__ = parent.prototype;
                  return child;
              };
              // The self-propagating extend function that Backbone classes use.
              // 實現對象繼承的函數, 該函數內部使用inherits實現繼承, 請參考inherits函數
              var extend = function(protoProps, classProps) {
                  var child = inherits(this, protoProps, classProps);
                  child.extend = this.extend;
                  return child;
              };
              // 獲取對象prop屬性的值, 如果prop屬性是一個函數, 則執行并返回該函數的返回值
              var getValue = function(object, prop) {
                  // 如果object為空或object不存在prop屬性, 則返回null
                  if(!(object && object[prop]))
                      return null;
                  // 返回prop屬性值, 如果prop是一個函數, 則執行并返回該函數的返回值
                  return _.isFunction(object[prop]) ? object[prop]() : object[prop];
              };
              // Set up inheritance for the model, collection, and view.
              // 為Model, Collection, Router和View類實現繼承機制
              Model.extend = View.extend = extend;
              
              exports.View = View;
              exports.Model = Model;
              
          })(PackTools);

          posted on 2014-06-26 09:43 koradji 閱讀(140) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          統計

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          收藏夾

          db2

          dos

          Groovy

          Hibernate

          java

          WAS

          web application

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 治县。| 嘉兴市| 江阴市| 闵行区| 简阳市| 镇原县| 红桥区| 南皮县| 丹寨县| 巴东县| 南昌县| 特克斯县| 德钦县| 连云港市| 噶尔县| 颍上县| 澄城县| 东乌珠穆沁旗| 濮阳县| 博乐市| 柘荣县| 疏勒县| 莱芜市| 龙胜| 清流县| 麻江县| 商南县| 元氏县| 鲜城| 塘沽区| 保亭| 通渭县| 阆中市| 仁布县| 吴川市| 封丘县| 宝清县| 佛教| 淳化县| 邓州市| 民和|