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;
      }
    });
  }
};

 

posted @ 2019-05-19 18:04  mysunshine_SZZ  阅读(1821)  评论(1编辑  收藏  举报