在vue2中:使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。
语法:
Object.defineProperty(目标对象,属性名,修饰符);
Object.defineProperty(obj, "name", { get:()=> {}, set:()=> {})
参数一: obj:劫持对象,参数二:"name":劫持对象属性 , 参数三:给属性添加set,get方法
示例:
let obj = { name: "tom", age: 10 };
Object.defineProperty(obj, "name", {
get: () => {
console.log("访问了name属性");
},
set: (newVule) => {
console.log("设置了name属性");
},
});
obj.name; //触发get
obj.name = "jack";//触发set
Vue2双向数据绑定存在的问题:
关于对象: Vue 无法检测 property 的添加或移除。
关于数组:不能利用索引直接设置一个数组项,也不能修改数组的长度。
原理:Vue3.0中的响应式采用了ES6中的 Proxy 方法。Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)
语法:
let p =new Proxy(obj,{get:(target,prop,p)=>{},set:(target, prop, vaule, p)=>{}})
参数: target:劫持对象,参数二:prop:劫持对象属性 , 参数三:vaule:新的属性值, p:本身
示例
let data = {
name:"老王",
age:18,
fun(){
console.log(this);
},
list:[1,2,3]
}
let proxy = new Proxy(data,{
get(target,pro){
console.log("get");
return Reflect.get(target,pro);
// return target[pro];
},
set(target,pro,value){
console.log("set");
// target[pro] = value;
Reflect.set(target,pro,value);
}
})
proxy.name = "小明";
console.log(proxy.name);
proxy.list[0] = 999;
总结:
vue2通过Object.defineProperty劫持的是对象中每一个属性
vue3通过Proxy劫持的是对象中每一个属性
为什么用Proxy代替Object.defineProperty?
Vue2.X通过Object.defineProperty()来劫持各个属性的setter,getter,新版本通过Proxy劫持属性 Proxy优势 支持数组,其实还不止
Object.defineProperty() 的问题主要有三个: 不能监听数组的变化 必须遍历对象的每个属性 必须深层遍历嵌套的对象
1,Object.definedProperty作用是劫持一个对象的属性,劫持属性的getter和setter方法,在对象的属性发生变化时进行特定的操作。而 Proxy 劫持的是整个对象。
Proxy 会返回一个代理对象,我们只需要操作新对象即可,而 Object.defineProperty只能遍历对象属性直接修改。
2,Object.definedProperty不支持数组,更准确的说是不支持数组的各种API,因为如果仅仅考虑arry[i] = value 这种情况,是可以劫持的,但是这种劫持意义不大。而Proxy 可以支持数组的各种API。
3,尽管 Object.defineProperty 有诸多缺陷,但是其兼容性要好于 Proxy.
PS: Vue2.x 使用 Object.defineProperty 实现数据双向绑定,V3.0 则使用了 Proxy