实现超简单响应式数据
利用Object.defineProperty
const objReactionProxy = new WeakMap()
let activeFn = null
class Depend {
constructor() {
this.reactiveFns = new Set()
}
addDepend() {
if (activeFn) {
this.reactiveFns.add(activeFn)
}
}
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
}
function watchFn(fn) {
activeFn = fn
fn()
activeFn = null
}
function getDepend(target, key) {
let keydepend = objReactionProxy.get(target)
if (!keydepend) {
keydepend = new Map()
objReactionProxy.set(target, keydepend)
}
let depend = keydepend.get(key)
if (!depend) {
depend = new Depend()
keydepend.set(key, depend)
}
return depend
}
function toProxy(target) {
Object.keys(target).forEach(key => {
let value = target[key]
Object.defineProperty(target, key, {
get() {
const depend = getDepend(target, key)
depend.addDepend()
return value
},
set(newV) {
value = newV
const depend = getDepend(target, key)
depend.notify()
},
})
})
return target
}
const obj = {
name: 'qqq',
age: 18,
}
const proxyObj = toProxy(obj)
watchFn(() => {
console.log('obj.name=====', proxyObj.name)
})
console.log('-----------------------')
proxyObj.name = 'ewq'
proxyObj.name = 'qwe'
proxyObj.name = 'asd'
利用Proxy
const objReactionProxy = new WeakMap()
let activeFn = null
class Depend {
constructor() {
this.reactiveFns = new Set()
}
addDepend() {
if (activeFn) {
this.reactiveFns.add(activeFn)
}
}
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
}
function watchFn(fn) {
activeFn = fn
fn()
activeFn = null
}
function getDepend(target, key) {
let keydepend = objReactionProxy.get(target)
if (!keydepend) {
keydepend = new Map()
objReactionProxy.set(target, keydepend)
}
let depend = keydepend.get(key)
if (!depend) {
depend = new Depend()
keydepend.set(key, depend)
}
return depend
}
function toProxy(target, options) {
return new Proxy(
target,
options ?? {
set(target, key, value, receiver) {
const depend = getDepend(target, key)
depend.notify()
return Reflect.set(target, key, value, receiver)
},
get(target, key, value, receiver) {
const depend = getDepend(target, key)
depend.addDepend()
return Reflect.get(target, key, value, receiver)
},
}
)
}
const obj = {
name: 'qqq',
age: 18,
}
const proxyObj = toProxy(obj)
watchFn(() => {
console.log('obj.name=====', proxyObj.name)
})
console.log('-----------------------')
proxyObj.name = 'ewq'
proxyObj.name = 'qwe'
proxyObj.name = 'asd'