1、简单的响应架构设计实现:
背景:有一个函数effect实现document.body.innerText的文本内容改变,body中的文本内容和一个data对象中的text属性相互绑定,当data对象中text属性改变时,body中的文本做出相应的改变;
设计原理:采用Proxy代理data数据,当代理对象获取到data属性text时,将effect函数放置一个桶中,即一个new Set() 的数据结构中,当代理对象改变data中的数据时,去遍历执行Set结构中的函数对象,从而达到更改body文本中的目的;
const data = {text:'hello world'}
const bucket = new Set();
const obj = new Proxy(data,{
get(target,key){
bucket.add(effect)
return target[key]
},
set(target,key,newVal){
target[key] = newVal
bucket.forEach(fn=>fn())
return true
}
})
function effect(){
document.body.innerText = obj.text
}
// 触发读取操作
effect()
// 1秒后修改
setTimeout(()=>{
obj.text = 'hello vue3'
},1000)
完善结构处理:
const data = {text:'hello world'}
const bucket = new WeakMap()
// 定义一个全局变量用来存储被注册的副作用函数
let activeEffect;
// 用来注册副作用函数
function effect(fn){
activeEffect = fn;
fn()
}
function track(target,key){
if(!activeEffect) return
let depsMap = bucket.get(target)
if(!depsMap){
bucket.set(target,depsMap = new Map())
}
let deps = depsMap.get(key)
if(!deps){
depsMap.set(key,deps = new Set())
}
deps.add(activeEffect)
}
function trigger(target,key){
const depsMap = bucket.get(target)
if(!depsMap) return
const effects = depsMap.get(key)
effects && effects.forEach(fn=>fn())
}
const obj = new Proxy(data,{
get(target,key){
track(target,key)
return target[key]
},
set(target,key,newVal){
target[key] = newVal
trigger(target,key)
}
})
effect(
()=>{
// console.log('effect run',bucket)
document.body.innerText = obj.text;
}
)
setTimeout(()=>{
obj.notExist = 'hello vue3'
},1000)
网友评论