vue(原理)_數據代理


 

1、數據代理:一個對象(A)來代理對另一個對象(B)的屬性操作(A一定要包含B)

2、vue中的數據代理:用vm實例對象來代替data 對data中的數據進行操作

  (1)vm實例代替data對象操作data對象中的name

    <div id="app">        
    </div>
    <script type="text/javascript" src="./vue.js"></script>
    <script type="text/javascript">
        const vm = new Vue({
            el:'#app',
            data:{
                name:'xxm'
            }
        })
        console.log(vm.name) //vm對象代替data對象讀取name,
        vm.name='szz' //vm對象代替data對象操作修改name 的值
        console.log(vm)
    </script>

  (2)分析:在控制台中打印輸出vm實例如下

vm實例對象中有_data對象里面存的是屬性,而在外面又有age,name屬性,通過調用vm里面的get()和set()方法就可以代理data對象,對data對象里面的屬性進行操作

 

 3、github上有個大佬仿vue實現了mvvm庫,下面通過mvvm庫來分析vue源碼中的數據代理

       地址:https://github.com/DMQ/mvvm

 

 

<script type="text/javascript" src="./mvvm/mvvm.js"></script>
    <script type="text/javascript" src="./mvvm/compile.js"></script>
    <script type="text/javascript" src="./mvvm/observer.js"></script>
    <script type="text/javascript" src="./mvvm/watcher.js"></script>
    <script type="text/javascript">
        const vm = new MVVM({
            el:'#app',
            data:{
                name:'xxm',
                age:18
            }

        })
        console.log(vm.name) //vm對象代替data對象讀取name,
        vm.name='szz' //vm對象代替data對象操作修改name 的值
        console.log(vm)

 

4、調試:

 

(1)第一步:在實例vm上添加斷點

 

 (2)第二步:點擊右側 "↓" 調試進入mvvm.js函數庫,進入MVVM函數庫繼續單步調試

 

 

 (3)第三步:點擊右側“↓”,進入到代理函數

(4)第四步:在加三個斷點(get(), set())如下

 

(5)第五步:點擊全部執行

(6)第六步:點擊執行 console.log(vm.name) 會跳到mvvm.js函數庫中,調用執行get()方法

 

 (7)第七步:繼續單步調試,會執行下面這一句,然后set監視到屬性,就會執行mvvm.js中的set()方法

 

 

 

5、數據代理主要用到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;
      }
    });
  }
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM