feat(effects): 实现响应式依赖收集和触发机制
- 创建targetMap WeakMap用于存储响应式对象及其依赖映射关系 - 实现track函数用于收集依赖并建立target-key-effect的映射 - 实现trigger函数用于触发指定key的依赖更新 - 在track中通过activeEffect判断是否需要收集依赖 - 添加详细的JSDoc注释说明参数和功能 - 示例页面中添加定时器验证响应式更新效果
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
type KeyToDepMap = Map<any, ReactiveEffect>
|
||||
/**
|
||||
* 收集所有依赖的WeakMap实例
|
||||
* key: 响应性对象
|
||||
* value: Map对象
|
||||
* key: 响应性对象的指定属性
|
||||
* value:指定对象的指定属性的执行函数
|
||||
*/
|
||||
const targetMap = new WeakMap<any, KeyToDepMap>()
|
||||
|
||||
export function effect<T = any>(fn: () => T) {
|
||||
const _effect = new ReactiveEffect(fn)
|
||||
_effect.run()
|
||||
@@ -15,19 +25,38 @@ export class ReactiveEffect<T = any> {
|
||||
|
||||
/**
|
||||
* 收集依赖
|
||||
* @param target
|
||||
* @param key
|
||||
* @param target WeakMap的key
|
||||
* @param key key代理对象的key, 当依赖被触发时,需要根据该key获取
|
||||
*/
|
||||
export function track(target: object, key: unknown) {
|
||||
console.log('收集依赖 track')
|
||||
if (!activeEffect) return
|
||||
//尝试从 targetMap 中, 根据target获取map
|
||||
let depsMap = targetMap.get(target)
|
||||
//如果获取到的map不存在,则生成新的map对象, 并把该对象赋值给对应的value
|
||||
if (!depsMap) {
|
||||
targetMap.set(target, (depsMap = new Map()))
|
||||
}
|
||||
//为指定map, 指定key, 设置回调函数
|
||||
depsMap.set(key, activeEffect)
|
||||
console.log(targetMap)
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发依赖
|
||||
* @param target
|
||||
* @param key
|
||||
* @param newValue
|
||||
* @param target WeakMap的key
|
||||
* @param key key代理对象的key, 当依赖被触发时,需要根据该key获取
|
||||
*/
|
||||
export function trigger(target: object, key: unknown, newValue: unknown) {
|
||||
console.log('触发依赖 trigger')
|
||||
//依据target获取存储的map实例
|
||||
const depsMap = targetMap.get(target)
|
||||
if (!depsMap) {
|
||||
return
|
||||
}
|
||||
//依据key, 从depsMap中取出value, 该value是一个ReactiveEffect类型的数据
|
||||
const effect = depsMap.get(key) as ReactiveEffect
|
||||
if (!effect) {
|
||||
return
|
||||
}
|
||||
//执行effect中保存的fn函数
|
||||
effect.fn()
|
||||
}
|
||||
|
||||
@@ -16,5 +16,8 @@
|
||||
effect(()=>{
|
||||
document.querySelector('#app').innerText=obj.name
|
||||
})
|
||||
setTimeout(()=>{
|
||||
obj.name='李四'
|
||||
},2000)
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user