1、簡單的響應(yīng)架構(gòu)設(shè)計實現(xiàn):
背景:有一個函數(shù)effect實現(xiàn)document.body.innerText的文本內(nèi)容改變,body中的文本內(nèi)容和一個data對象中的text屬性相互綁定,當data對象中text屬性改變時,body中的文本做出相應(yīng)的改變;
設(shè)計原理:采用Proxy代理data數(shù)據(jù),當代理對象獲取到data屬性text時,將effect函數(shù)放置一個桶中,即一個new Set() 的數(shù)據(jù)結(jié)構(gòu)中,當代理對象改變data中的數(shù)據(jù)時,去遍歷執(zhí)行Set結(jié)構(gòu)中的函數(shù)對象,從而達到更改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
}
// 觸發(fā)讀取操作
effect()
// 1秒后修改
setTimeout(()=>{
obj.text = 'hello vue3'
},1000)
完善結(jié)構(gòu)處理:
const data = {text:'hello world'}
const bucket = new WeakMap()
// 定義一個全局變量用來存儲被注冊的副作用函數(shù)
let activeEffect;
// 用來注冊副作用函數(shù)
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)