| 
                            
                                  effect的基本实现
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | export let activeEffect = undefined;// 当前正在执行的effect class ReactiveEffect {     active = true;     deps = []; // 收集effect中使用到的属性     parent = undefined;     constructor(public fn) { }     run() {         if (!this.active) { // 不是激活状态             return this.fn();         }         try {             this.parent = activeEffect; // 当前的effect就是他的父亲             activeEffect = this; // 设置成正在激活的是当前effect             return this.fn();         } finally {             activeEffect = this.parent; // 执行完毕后还原activeEffect             this.parent = undefined;         }     } } export function effect(fn, options?) {     const _effect = new ReactiveEffect(fn); // 创建响应式effect     _effect.run(); // 让响应式effect默认执行 } |  依赖收集
	
		
			| 1 2 3 4 5 6 7 8 | get(target, key, receiver) {     if (key === ReactiveFlags.IS_REACTIVE) {         return true;     }     const res = Reflect.get(target, key, receiver);     track(target, 'get', key);  // 依赖收集     return res; } |  
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const targetMap = new WeakMap(); // 记录依赖关系 export function track(target, type, key) {     if (activeEffect) {         let depsMap = targetMap.get(target); // {对象:map}         if (!depsMap) {             targetMap.set(target, (depsMap = new Map()))         }         let dep = depsMap.get(key);         if (!dep) {             depsMap.set(key, (dep = new Set())) // {对象:{ 属性 :[ dep, dep ]}}         }         let shouldTrack = !dep.has(activeEffect)         if (shouldTrack) {             dep.add(activeEffect);             activeEffect.deps.push(dep); // 让effect记住dep,这样后续可以用于清理         }     } } |  将属性和对应的effect维护成映射关系,后续属性变化可以触发对应的effect函数重新run 触发更新
	
		
			| 1 2 3 4 5 6 7 8 9 | set(target, key, value, receiver) {     // 等会赋值的时候可以重新触发effect执行     let oldValue = target[key]     const result = Reflect.set(target, key, value, receiver);     if (oldValue !== value) {         trigger(target, 'set', key, value, oldValue)     }     return result; } |  
	
		
			| 1 2 3 4 5 6 7 8 9 10 | export function trigger(target, type, key?, newValue?, oldValue?) {     const depsMap = targetMap.get(target); // 获取对应的映射表     if (!depsMap) {         return     }     const effects = depsMap.get(key);     effects && effects.forEach(effect => {         if (effect !== activeEffect) effect.run(); // 防止循环     }) } |  分支切换与cleanup在渲染时我们要避免副作用函数产生的遗留 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 | const state = reactive({ flag: true, name: 'jw', age: 30 }) effect(() => { // 副作用函数 (effect执行渲染了页面)     console.log('render')     document.body.innerHTML = state.flag ? state.name : state.age }); setTimeout(() => {     state.flag = false;     setTimeout(() => {         console.log('修改name,原则上不更新')         state.name = 'zf'     }, 1000); }, 1000) |  
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function cleanupEffect(effect) {     const { deps } = effect; // 清理effect     for (let i = 0; i < deps.length; i++) {         deps[i].delete(effect);     }     effect.deps.length = 0; } class ReactiveEffect {     active = true;     deps = []; // 收集effect中使用到的属性     parent = undefined;     constructor(public fn) { }     run() {         try {             this.parent = activeEffect; // 当前的effect就是他的父亲             activeEffect = this; // 设置成正在激活的是当前effect +           cleanupEffect(this);             return this.fn(); // 先清理在运行         }     } } |  这里要注意的是:触发时会进行清理操作(清理effect),在重新进行收集(收集effect)。在循环过程中会导致死循环。 
	
		
			| 1 2 3 | let effect = () => {}; let s = new Set([effect]) s.forEach(item=>{s.delete(effect); s.add(effect)}); // 这样就导致死循环了 |  停止effect
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | export class ReactiveEffect {     stop(){         if(this.active){              cleanupEffect(this);             this.active = false         }     } } export function effect(fn, options?) {     const _effect = new ReactiveEffect(fn);      _effect.run();     const runner = _effect.run.bind(_effect);     runner.effect = _effect;     return runner; // 返回runner } |  调度执行trigger触发时,我们可以自己决定副作用函数执行的时机、次数、及执行方式 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | export function effect(fn, options:any = {}) {     const _effect = new ReactiveEffect(fn,options.scheduler); // 创建响应式effect     // if(options){     //     Object.assign(_effect,options); // 扩展属性     // }     _effect.run(); // 让响应式effect默认执行     const runner = _effect.run.bind(_effect);     runner.effect = _effect;     return runner; // 返回runner } export function trigger(target, type, key?, newValue?, oldValue?) {     const depsMap = targetMap.get(target);     if (!depsMap) {         return     }     let effects = depsMap.get(key);     if (effects) {         effects = new Set(effects);         for (const effect of effects) {             if (effect !== activeEffect) {                  if(effect.scheduler){ // 如果有调度函数则执行调度函数                     effect.scheduler()                 }else{                     effect.run();                  }             }         }     } } |  深度代理 
	
		
			| 1 2 3 4 5 6 7 8 9 10 11 12 | get(target, key, receiver) {     if (key === ReactiveFlags.IS_REACTIVE) {         return true;     }     // 等会谁来取值就做依赖收集     const res = Reflect.get(target, key, receiver);     track(target, 'get', key);     if(isObject(res)){         return reactive(res);     }     return res; } |  当取值时返回的值是对象,则返回这个对象的代理对象,从而实现深度代理 总结为了实现响应式,我们使用了new Proxy effect默认数据变化要能更新,我们先将正在执行的effect作为全局变量,渲染(取值),然后在get方法中进行依赖收集 依赖收集的数据格式weakMap(对象:map(属性:set(effect)) 用户数据发生变化,会通过对象属性来查找对应的effect集合,全部执行; 调度器的实现,创建effect时,把scheduler存在实例上,调用runner时,判断如果有调度器就调用调度器,否则执行runner 
 |