vue2.0与vue3.0的区别(1)

586 阅读2分钟

这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

响应式的实现

vue2.0: 使用es5的definedProperty属性对该对象通过 递归+遍历的方式来实现对数据的监控,但是此属性不能监听数组,对象的删除、新增等操作。

vue3.0: 使用ES6的proxy属性让实例里的data具有响应式功能,包括一下几点:

  • 可以监听动态新增的属性;
  • 可以监听删除的属性 ;
  • 可以监听数组的变化;

es5的definedProperty双向绑定示例:

var obj = {}
obj.name="liudan"
obj.age = 18
Object.defineProperty(obj,'changePro',{
    get(){
        return this.name +this.age
    }
    set(val){
        const info = val,split('-')
        this.name = info[0]
        this.age = info[1]
    }
    console.log(obj.name,obj.age,obj.changePro)
    //liudan 18  liudan18
    obj.name = 'huashiyun'
    console.log(obj.changePro)
    //huashiyun18
    obj.changePro = 'huashiyun-20'
    console.log(obj.name,obj.age)
    //huashiyun  20
}

但是,比如当我们使用数组的方法或改变数组的下标是不能重新触发 Object.defineProperty中的set()方法的,所以vue2.0实现双向绑定有一定的局限性

ES6的proxy属性:

据阮一峰文章介绍:

Proxy可以理解成,在目标对象之前架设一层 "拦截",当外界对该对象访问的时候,都必须经过这层拦截,而Proxy就充当了这种机制,类似于代理的含义,它可以对外界访问对象之前进行过滤和改写该对象。

Proxy基本语法

const obj = new Proxy(target, handler); 参数说明如下:

target:  被代理对象。
handler:  是一个对象,声明了代理target的一些操作。
obj:  是被代理完成之后返回的对象。

但是当外界每次对obj进行操作时,就会执行handler对象上的一些方法。handler中常用的对象方法如下:

1. get(target, propKey, receiver)
2. set(target, propKey, value, receiver)
3. has(target, propKey)
4. construct(target, args):
5. apply(target, object, args)

如上是Proxy中handler 对象的方法,其实它和Reflect里面的方法类似的,想要了解Reflect看这篇文章

示例:


const target = {
  name: 'kongzhi'
};

const handler = {
  get: function(target, key) {
    console.log(`${key} 被读取`);
    return target[key];
  },
  set: function(target, key, value) {
    console.log(`${key} 被设置为 ${value}`);
    target[key] = value;
  }
};

const testObj = new Proxy(target, handler);

/*
  获取testObj中name属性值
  会自动执行 get函数后 打印信息:name 被读取 及输出名字 kongzhi
*/
console.log(testObj.name);//name 被读取 kongzhi

/*
 改变target中的name属性值
 打印信息如下: name 被设置为 111 
*/
testObj.name = 111;

console.log(target.name); // 输出 111 

如上代码所示:也就是说 target是被代理的对象,handler是代理target的,那么handler上面有set和get方法,当每次打印target中的name属性值的时候会自动执行handler中get函数方法,当每次设置 target.name 属性值的时候,会自动调用 handler中的set方法,因此target对象对应的属性值会发生改变,同时改变后的 testObj对象也会发生改变。同理改变返回后 testObj对象中的属性也会改变原对象target的属性的,因为对象是引用类型的,是同一个引用的。

更精准的变更通知

vue2.0使用Vue.$set新增一个属性时,依赖于这个属性的watch对象都会被触发。但是Vue3.0则优化了,新增属性时只会通知具体依赖于这个属性的watch