在开始正文前,先理一下vue2 Object.defineProperty 和 vue 3 Proxy 区别:
Object.defineProperty:数据劫持
Proxy:数据代理
注意:
响应式原理和双向数据绑定原理是两回事,一般面试官会先问响应式原理再问双向数据绑定的原理
详细文章
1.什么是proxy?
在目标对象前架设一层“拦截”,当外界对该对象进行访问的时候,都需要经过这层拦截,而proxy充当的就是这种机制,类似于“代理”的意思,可以在外界访问该对象前进行过滤和改写。
(我自己理解的意思就是: 我不直接操作target,而是通过proxy代理target,然后通过handler里的方法来进行一些“拦截”,然后对该对象进行操作。)
2.Proxy的基本语法
let obj = new Proxy(target,handler)
// target:目标对象(你要进行处理的对象)
// handler:容器(无数可以处理对象属性的方法)
var obj = { a: 1, b: 2 };
let proxy = new Proxy(obj, {
get(target, prop) {
console.log('get方法')
return target[prop]; // prop:obj对象里的属性a、b ,类似于key
},
set(target, prop, value) {
target[prop] = value; // value:新值
console.log('set方法')
},
});
proxy.a = 4;
console.log(obj.a); //4
3.Object.defineProperty() 和 Proxy 的区别
Proxy
-
优点:
1.可以直接监听对象而非属性
2.可以直接监听数组的变化
3.有13种拦截方法(Object.defineProperty() 没有)
4.返回的是一个新对象,我们可以直接操作新对象来达到目的,而Object.defineProperty() 只能遍历对象属性直接修改
5.性能优化 -
缺点:
无法兼容所有浏览器,无法进行polyfill
Object.defineProperty()
- 优点:
兼容性较好 - 缺点:
1.无法对数组进行监听,采用的是对数组的方法进行重写(push、pop、shift、unshift等),对此进行双向绑定和数据监听的操作
2.效率差,因为对多层数据进行一次性的递归操作,当数组多时,非常影响性能
4.handler常见方法(详细描述可见es6中的Reflect)
reflect对象的原型就是Object
1)将 object对象的一些明显属性语言内部的方法(如 Object.defineProperty)放到reflect 对象上,就能从 reflect 对象上拿到语言内部的方法
2)在使用对象的 Object.defineProperty(obj, name, {})时,如果出现异常的话,会抛出一个错误,需要使用try catch去捕获,但是使用 Reflect.defineProperty(obj, name, desc) 则会返回false
var obj = { a: 1, b: 2 };
let proxy = new Proxy(obj, {
get(target, prop) {
return target[prop]; // prop:obj对象里的属性a、b ,类似于key
console.log('get方法');
},
set(target, prop, value) {
// target[prop] = value; // value:新值
Reflect.set(target, prop, value);
console.log('set方法');
},
});
proxy.a = 4;
console.log(obj.a); //4
5.如何实现的?
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过new Proxy()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
Vue 3.0与Vue 2.0的区别仅是数据劫持的方式由Object.defineProperty更改为Proxy代理,其他代码不变。