友友们大家好,vue3推出后大家有没有去看呢?博主是个性子急的人,哪能禁得住这诱惑。
经过博主粗略的阅读,我感觉vue3最大的变化之一便是使用Proxy取代defineProperty去实现数据劫持。
让我们想一想,为什么会这样呢?
不知道大家有没有遇到过,在项目中改变数组或给对象添加属性,视图并没有相应式的更新。这其实就是defineProperty的一个缺陷,下面我将会给大家详细介绍Proxy和取代defineProperty的原因。
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
const proxy = new Proxy(target, handler);
Proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。其中,new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
若handler参数为空对象,则返回原属性值。
例如:
const proxy = new Proxy({}, {
// get方法的两个参数分别是目标对象和所要访问的属性
get: function(target, propKey) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
proxy.title // 35
上述代码中,对target(本例中的空对象)进行了拦截,由于拦截函数总是返回35,所以访问的所有属性都返回35。
下面介绍handler参数里的set和get方法:
get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
例如:
const obj = { a: 1 };
const proxy = new Proxy(obj, {
get: function (target, propKey) {
if (target[propKey]) {
return target[propKey];
} else {
return "我没有";
}
},
});
console.log(proxy.a);
console.log(proxy.b);
const obj = { a: 1 };
const proxy = new Proxy(obj, {
get: function (target, propKey) {
if (target[propKey]) {
return target[propKey];
} else {
return "我没有";
}
},
});
const obj1 = Object.create(proxy);
console.log(obj1.a);
console.log(obj1.b);
set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
通俗一点说就是get是在读取数据做处理,set是在赋值做处理。
例如:
const obj = { a: 1 };
const proxy = new Proxy(obj, {
set: function (obj, key, value) {
if (key === "age") {
if (value <= 20) {
console.log("年轻人");
} else {
console.log("老人");
}
}
},
});
proxy.age = 17;
我们可以利用set来进行属性赋值的校验,比如年龄只能到0-100之间的操作。
以上我们只简单介绍proxy的常用方法,如果有兴趣的同学,可以看一看阮一峰的es6标准入门学习一下哦
大家都知道,vue2.x的双向绑定原理是利用数据劫持结合发布订阅模式实现的。
可以简化为下面几步:
vue是怎么解决这个问题呢,也就是我们在vue2.x里该怎么去解决这个问题呢?
这个部分可以去看我的另一篇文章哦,传送门:解决vue中改变数组视图不更新
由上可以看出,vue3使用proxy的原因:
但是proxy由于是es6的方法,所以也会存在着兼容性的问题
本文只是简单介绍了为什么vue使用proxy的原因,如果有小伙伴感兴趣可以去研究研究哦。