console
const bucket = new WeakMap()
const effectStack = []
let activeEffect
const effect = function (fn) {
const effectFn = () => {
cleanUp(effectFn)
activeEffect = effectFn
effectStack.push(effectFn)
fn()
effectStack.pop()
activeEffect = effectStack[effectStack.length - 1]
}
effectFn.deps = []
effectFn()
}
function cleanUp(effectFn) {
for (let i = 0; i < effectFn.deps.length; i++) {
const deps = effectFn.deps[i]
deps.delete(effectFn)
}
effectFn.deps.length = 0
}
function trackFunc(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
}
let deps = depsMap.get(key)
if (deps) {
deps = new Set(deps)
deps.forEach(fn => fn())
}
}
function reactive(data) {
return new Proxy(data, {
get: (target, key) => {
const value = target[key]
trackFunc(target, key)
return value
},
set: (target, key, newValue) => {
target[key] = newValue
trigger(target, key)
}
})
}
const state2 = reactive({
foo: true,
bar: true
})
effect(function effectFn1 () {
console.log('effectFn1-----------***************')
effect(function effectFn2 () {
console.log('effectFn2--------//////////////')
console.log('Bar----------', state2.bar)
})
console.log('Foo------', state2.foo)
})
setTimeout(() => {
state2.foo = false
}, 5000)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
#app{
width: 200px;
height: 100px;
background-color: #ffffff;
}