Reactivity模块基本使用
<div id="app"></div>
<script src="./reactivity.global.js"></script>
<script>
const { reactive, effect, shallowReactive, shallowReadonly, readonly } = VueReactivity;
// let state = reactive({ name: 'jw', age: 30 });
// const state = shallowReactive({ name: 'jw', age: 30 })
// const state = readonly({ name: 'jw', age: 30 })
const state = reactive({ name: 'jw', age: 30})
effect(() => { // 副作用函数 (effect执行渲染了页面)
app.innerHTML = state.name + '今年' + state.age + '岁了'
});
setTimeout(() => {
state.age++;
}, 1000)
</script>
reactive
方法会将对象变成proxy对象,effect
中使用reactive
对象时会进行依赖收集,稍后属性变化时会重新执行effect
函数。
编写reactive函数
const reactiveMap = new WeakMap(); // 缓存列表
const mutableHandlers: ProxyHandler<object> = {
get(target, key, receiver) {
// 等会谁来取值就做依赖收集
const res = Reflect.get(target, key, receiver);
return res;
},
set(target, key, value, receiver) {
// 等会赋值的时候可以重新触发effect执行
const result = Reflect.set(target, key, value, receiver);
return result;
}
}
function createReactiveObject(target: object, isReadonly: boolean) {
if (!isObject(target)) {
return target
}
const exisitingProxy = reactiveMap.get(target); // 如果已经代理过则直接返回代理后的对象
if (exisitingProxy) {
return exisitingProxy;
}
const proxy = new Proxy(target, mutableHandlers); // 对对象进行代理
reactiveMap.set(target,proxy)
return proxy;
}
这里必须要使用Reflect进行操作,保证this指向永远指向代理对象
let school = {
name:'zf',
get num(){
return this.name;
}
}
let p = new Proxy(school,{
get(target, key,receiver){
console.log(key);
// return Reflect.get(target,key,receiver)
return target[key]
}
})
p.num
将对象使用proxy进行代理,如果对象已经被代理过,再次重复代理则返回上次代理结果。 那么,如果将一个代理对象传入呢?