这是我参与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