依赖收集,简单版
let price = 5
let num = 2
let total = 0
const DepSet = new Set()
let effect = () => {
total = price * num
}
const track = () => {
DepSet.add(effect)
}
const trigger = () => {
DepSet.forEach(effect => effect())
}
track()
trigger()
console.log(total)
num = 5
track()
trigger()
console.log(total)
响应式依赖收集,多个依赖版
const DepMap = new Map()
function track(key) {
let DepSet = DepMap.get(key)
if (!DepSet) {
DepSet = new Set()
DepMap.set(key, DepSet)
}
DepSet.add(effect)
}
function trigger(key) {
const DepSet = DepMap.get(key)
if (DepSet) {
DepSet.forEach(effect => effect())
}
}
const product = {
price: 10,
num: 2,
}
let total = 0
let effect = () => (total = product.price * product.num)
track('num')
effect()
console.log(total)
product.num = 5
trigger('num')
console.log(total)
响应式依赖收集,多个响应式收集
const targetMap = new WeakMap()
function track(target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap = new Map()
targetMap.set(target, depsMap)
}
let depsSet = depsMap.get(key)
if (!depsSet) {
depsSet = new Set()
depsMap.set(key, depsSet)
}
depsSet.add(effect)
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const depsSet = depsMap.get(key)
depsSet.forEach(effect => effect())
}
const product = {
price: 10,
num: 3,
}
let total = 0
function effect() {
total = product.num * product.price
}
track(product, 'num')
effect()
console.log(total)
product.num = 5
trigger(product, 'num')
console.log(total)
结合proxy,自动触发trigger
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(target, key)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
trigger(target, key)
},
}
return new Proxy(target, handler)
}
const targetMap = new WeakMap()
function track(target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap = new Map()
targetMap.set(target, depsMap)
}
let depsSet = depsMap.get(key)
if (!depsSet) {
depsSet = new Set()
depsMap.set(key, depsSet)
}
depsSet.add(effect)
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const depsSet = depsMap.get(key)
if (depsSet) {
depsSet.forEach(effect => effect())
}
}
const product = {
price: 10,
num: 2,
}
let total = 0
const proxyProduct = reactive(product)
function effect() {
total = proxyProduct.price * proxyProduct.num
}
effect()
console.log(total)
proxyProduct.num = 5
console.log(total)
proxyProduct.price = 20
console.log(total)
activeEffect
let activeEffect = null
let targetMap = new WeakMap()
function effect(eff) {
activeEffect = eff
activeEffect()
activeEffect = null
}
function reactive(orogin) {
return new Proxy(orogin, {
get(target, key, reveice) {
track(target, key)
return Reflect.get(target, key, reveice)
},
set(target, key, value, reveice) {
Reflect.set(target, key, value, reveice)
trigger(target, key)
},
})
}
function track(target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap = new Map()
targetMap.set(target, depsMap)
}
let depsSet = depsMap.get(key)
if (!depsSet) {
depsSet = new Set()
depsMap.set(key, depsSet)
}
if (activeEffect) {
depsSet.add(activeEffect)
}
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const depsSet = depsMap.get(key)
if (depsSet) {
depsSet.forEach(effect => {
effect()
})
}
}
const product = {
price: 10,
num: 2,
}
let total = 0
const proxyProduct = reactive(product)
effect(() => {
total = proxyProduct.num * proxyProduct.price
})
console.log(total)
proxyProduct.price = 50
console.log(total)
proxyProduct.num = 1
console.log(total)