reactive函数功能
在Vue3.0中,reactive函数通过为当前对象生成代理对象,实现数据的响应式功能。即为用户数据生成代理对象,从而实现监控用户数据改变的目的。
本文通过实现一个类似功能的模拟reactive函数,来帮助大家更好的理解Vue 3.0的数据代理原理。
基本思路
在Vue 3.0中所谓生成代理类对象,即生成ES6的Proxy对象。由该对象代理当前数据的修改操作,即当前数据的任何改变,该代理对象都可以监控到。
Proxy对象的构造方法有两个参数,参数1为要代理的数据,要求该数据为object类型;参数2是一个Handler,包含get和set两个方法。代理对象的数据读取,将触发get方法;代理对象的数据修改,将触发set方法。
因为要为用户数据的所有属性生成代理,所以模拟代码采用递归的形式,只要该属性对应的值是object类型,则为该属性加上代理。
reactive函数模拟代码如下:
(function(window){
const get = () => (target,key,receiver) => {
const obj = Reflect.get(target,key,receiver);
console.log(`Get key: ${key} from current object.`);
if (isObject(obj)){
return reactive(obj);
}
return obj;
}
const set = () => (target, key, value, receiver) => {
const hasKey = isExisted(target, key);
const oldValue = Reflect.get(target,key,receiver);
const obj = Reflect.set(target ,key, value, receiver);
if (hasKey){
console.log(`Key ${key}'s value is changed from ${oldValue} to ${value}`);
}else{
console.log(`Add new Key ${key} to object. Value is ${value}`);
}
return obj;
}
const isObject = target => typeof target === 'object' && target != null
const isExisted = (target,key) => Object.hasOwnProperty.call(target,key);
const reactiveHandler = {
get: get(),
set: set(),
}
const createReactive = (target,reactiveHandler) => {
if (!isObject(target)){
return target;
}
var observer = new Proxy(target,reactiveHandler);
return observer;
}
const reactive = target => {
return createReactive(target,reactiveHandler);
}
window.reactive = window.reactive || reactive;
})(window);
使用方法
- 执行上述代码
- 创建对象如下,并调用函数生成该数据的代理对象:
var obj = {a:1,b:{c:1,d:[1,2,3]}};
var observer = reactive(obj);
- 读取代理对象中的属性,执行结果如下。代理对象的数据读取,可以被监控到。
observer.a;
observer.b.c;
4. 读取源数据中的属性, 从截图中可以看出,代理对象的get方法并没有被触发。这也是Vue 2.0和Vue 3.0的不同,Vue 2.0是通过Object.defineProperties,做的数据劫持,即修改了用户数据,来实现数据修改的监控。而Vue 3.0是通过代理实现数据监控,只有修改代理对象中的数据,才会监控到修改。
5. set操作同get操作,不再赘述。