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