vue进阶-数据劫持与数据代理

vue中最核心的一个点就是响应式数据,数据发生变化,视图也随之变化,实现响应式的一个重要的知识点就是数据劫持,对数据的取值与赋值进行拦截操作,并附加一些其他的操作

一.es5的Object.defineProperty

这个api是vue1.x与vue2.x实现数据劫持的一个非常重要的api,方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。在前面的对象深入学习中已经详细的说明了,这里就不在赘述了,

1.vue中是如何实现数据劫持的?

       function defineReactive () {
       //这个是一个中间变量,用于存储属性的真正的值,每次取值或者存值都是对这个属性的操作
            var num;
            Object.defineProperty(obj, 'num', {
                // 可遍历
                enumerable: true,
                // 不可再配置
                configurable: false,
                get: () => {
                    return num
                },
                set: (newValue) => {
                    num = newValue
                }
            });
        }

进一步改进

function defineReactive (data, key, value) {
    //这里用到了闭包的原理,每个函数里面的参数都拥有自己的作用域,就不用显示的申明一个中间变量了
    Object.defineProperty(data, key, {
      // 可遍历
      enumerable: true,
      // 不可再配置
      configurable: false,
      get: () => {
        return value
      },
      set: (newValue) => {
        value = newValue
      }
    });
  }

这里需要使用中间变量是因为不能在object.defineproperty中使用data[key]的方式去取原来的值,会形成死循环,因为这种方式会触发我们给这个属性定义的拦截

2.数据代理

vue中我们会经常使用到data里定义的属性,methods里定义的方法,computed定义的计算属性等,我们在使用的时候都是可以直接通过this[property]的方式来访问,其实实现的原理十分的简单,代码演示:

  _proxyData(data) {
    Object.keys(data).forEach(key => {
      Object.defineProperty(this, key, {
        set(newValue) {
          data[key] = newValue;
        },
        get() {
          return data[key];
        }
      });
    });
  }
  _proxyMethod(methods) {
    if (methods && typeof methods === "object") {
      Object.keys(methods).forEach(key => {
        this[key] = methods[key];
      });
    }
  }

上面就是对我们访问属性进行了拦截

你可能感兴趣的:(es6,vue)