关联数据和函数
依赖收集
实现Effect
这里直接给出 Effect 实现:
js
/**
* 用于记录当前活动的 effect
*/
export let activeEffect = undefined;
export const targetMap = new WeakMap(); // 用来存储对象和其属性的依赖关系
const effectStack = [];
/**
* 该函数的作用,是执行传入的函数,并且在执行的过程中,收集依赖
* @param {*} fn 要执行的函数
*/
export function effect(fn) {
const environment = () => {
try {
activeEffect = environment;
effectStack.push(environment);
cleanup(environment);
return fn();
} finally {
effectStack.pop();
activeEffect = effectStack[effectStack.length - 1];
}
};
environment.deps = [];
environment();
}
export function cleanup(environment) {
let deps = environment.deps; // 拿到当前环境函数的依赖(是个数组)
if (deps.length) {
deps.forEach((dep) => {
dep.delete(environment);
});
deps.length = 0;
}
}
改造track
之前 track 仅仅只是简单的打印,那么现在就不能是简单打印了,而是进行具体的依赖收集。
注意依赖收集的时候,需要按照上面的设计一层一层进行查找。
改造trigger
trigger 要做的事情也很简单,就是从我们所设计的数据结构里面,一层一层去找,找到对应的依赖函数集合,然后全部执行一次。
首先我们需要建立一个设置行为和读取行为之间的映射关系:
js
// 定义修改数据和触发数据的映射关系
const triggerTypeMap = {
[TriggerOpTypes.SET]: [TrackOpTypes.GET],
[TriggerOpTypes.ADD]: [
TrackOpTypes.GET,
TrackOpTypes.ITERATE,
TrackOpTypes.HAS,
],
[TriggerOpTypes.DELETE]: [
TrackOpTypes.GET,
TrackOpTypes.ITERATE,
TrackOpTypes.HAS,
],
};
我们前面在建立映射关系的时候,是根据具体的获取信息的行为来建立的映射关系,那么我们获取信息的行为有:
- GET
- HAS
- ITERATE
这些都是在获取成员信息,而依赖函数就是和这些获取信息的行为进行映射的。
因此在进行设置操作的时候,需要思考一下当前的设置,会涉及到哪些获取成员的行为,然后才能找出该行为所对应的依赖函数。
懒执行
有些时候我们想要实现懒执行,也就是不想要传入 effect 的回调函数自动就执行一次,通过配置项来实现
添加回调
有些时候需要由用户来指定是否派发更新,支持用户传入一个回调函数,然后将要依赖的函数作为参数传递回给用户给的回调函数,由用户来决定如何处理。
-EOF-