1. 程式人生 > >MVVM(一)資料代理原始碼分析

MVVM(一)資料代理原始碼分析

1:準備工作API瞭解

  1. 1.  [].slice.call(lis): 將偽陣列轉換為真陣列
    2. node.nodeType: 得到節點型別
    3. Object.defineProperty(obj, propertyName, {}): 給物件新增屬性(指定描述符)
    4. Object.keys(obj): 得到物件自身可列舉屬性組成的陣列
    5. obj.hasOwnProperty(prop): 判斷prop是否是obj自身的屬性
    6. DocumentFragment: 文件碎片(高效批量更新多個節點)

MVVM原始碼分析:

(一)資料代理實現

1.  
vue資料代理: data物件的所有屬性的操作(讀/寫)由vm物件來代理操作
2. 好處: 通過vm物件就可以方便的操作data中的資料
3. 實現:
  1). 通過Object.defineProperty(vm, key, {})給vm新增與data物件的屬性對應的屬性
  2). 所有新增的屬性都包含get/set方法
  3). 在get/set方法中去操作data中對應的屬性
function MVVM(options) {
  // 將選項物件儲存到vm
  this.$options = options;
  // 將data物件儲存到vm和datq變數中
  var data = this._data = this.$options.data;
  //將vm儲存在me變數中
  var me = this;
  // 遍歷data中所有屬性
  Object.keys(data).forEach(function (key) { // 屬性名: name
    // 對指定屬性實現代理
    me._proxy(key);
  });
}
const vm = new MVVM({
    el: "#test",
    data: {
      name: '張三2' //配置物件的data屬性
    }
  })
  console.log(vm.name)  // 讀取的是data中的name,  vm代理對data的讀操作
  vm.name = '李四2' // 資料儲存到data中的name上, vm代理對data的寫操作
  // 對指定屬性實現代理
  _proxy: function (key) {
    // 儲存vm
    var me = this;
    // 給vm新增指定屬性名的屬性(使用屬性描述)
    Object.defineProperty(me, key, {
      configurable: false, // 不能再重新定義
      enumerable: true, // 可以列舉
      // 當通過vm.name讀取屬性值時自動呼叫
      get: function proxyGetter() {
        // 讀取data中對應屬性值返回(實現代理讀操作)
        return me._data[key];
      },
      // 當通過vm.name = 'xxx'時自動呼叫
      set: function proxySetter(newVal) {
        // 將最新的值儲存到data中對應的屬性上(實現代理寫操作)
        me._data[key] = newVal;
      }
    });
  }
};

  

    實現思路:在建立VM物件的時候,將配置物件的data屬性存放到vm_data裡面,然後data中的屬性通過通過Object.defineProperty(vm, key, {})給vm新增與data物件的屬性對應的屬性,在讀取data屬性的時候呼叫get方法,設定的時候呼叫get方法。

 

VM物件的$option存放的是配置物件,_data存放的是data的資料,實現讀取data資料都是在_data中讀取。實現關鍵就是Object.defineProperty(vm, key, {});