1. 程式人生 > >vue原始碼解析 —— 資料代理

vue原始碼解析 —— 資料代理

1. 前言:因為vue原始碼是比較複雜的,考慮的東西比較多;而這裡只是簡單的瞭解下類似vue的mvvm框架的部分原理,所以我們用這個庫: https://github.com/DMQ/mvvm  (仿vue實現的mvvm庫,比vue簡介,簡單) ==>> 下面稱其為 mvvm

2. 概念解析:

1) 資料代理: 通過一個物件代理對另一個物件(在前一個物件內部)中屬性的操作(讀/寫)
2) vue 資料代理: 通過 vm 物件(即this)來代理 data 物件中所有屬性的操作
3) 好處: 更方便的操作 data 中的資料
4) 基本實現流程
a. 通過 Object.defineProperty()給 vm 新增與 data 物件的屬性對應的屬性描述符
b. 所有新增的屬性都包含 getter/setter
c. getter/setter 內部去操作 data 中對應的屬性資料

3. 基本實現  (vue實現資料代理 / mvvm實現資料代理)

3.1 vue實現資料代理

3.2 mvvm實現資料代理

 

4. mvvm中資料代理的原始碼(主要由Object.definePropert這個方法實現 mvvm中的mvvm.js)

/*
相關於Vue的建構函式
 */
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);
  });

  // 對data進行監視
  observe(data, this);

  // 建立一個用來編譯模板的compile物件
  this.$compile = new Compile(options.el || document.body, this)
}

MVVM.prototype = {
  $watch: function (key, cb, options) {
    new Watcher(this, key, cb);
  },

  // 對指定屬性實現代理   ===>>> 最重要的程式碼
  _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;
      }
    });
  }
};

 

5. chrome瀏覽器的除錯按鈕

 

文章僅為本人學習過程的一個記錄,僅供參考,如有問題,歡迎指出!