Skip to content
On this page

EffectScope

effectScope是一个函数,调用effectScope函数会返回一个对象,其中包含了run 和stop;在run中定义的所有effect函数,在调用了scope对象的stop()方法之后,所有的依赖都被停止了。

const {effectScope,reactive,effect} = VueReactivity; 
const scope = effectScope(true);
scope.run(()=>{
    const state = reactive({age:13});
    effect(()=>{
        console.log(state.age);
    });
    setTimeout(()=>{
        state.age++;
    },1000)
});
scope.run(()=>{
    const state = reactive({age:13});
    effect(()=>{
        console.log(state.age);
    });
    setTimeout(()=>{
        state.age++;
    },1000)
});
scope.stop(); // 停止scope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

收集Effect

export let activeEffectScope;
class EffectScope{
    active = true;
    effects = [];
	parent
    run(fn){
        if(this.active){ // 如果激活
            try{
               activeEffectScope = this; // 保存activeEffectScope
               return fn();
            }finally{
               activeEffectScope = this.parent; // 还原activeEffectScope
            }
        }
    }
}
export function recordEffectScope(effect){ // 将effect收集到activeEffectScope中
    if(activeEffectScope && activeEffectScope.active){ 
        activeEffectScope.effects.push(effect);
    }
}
export class ReactiveEffect {
    // 这里表示在实例上新增了active属性
    public parent = null;
    public deps = []
    public active = true; // 这个effect默认是激活状态
    constructor(public fn,public scheduler?){
        recordEffectScope(this)
    } 
}
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
30

实现stop、run方法

let activeEffectScope;
class EffectScope{
    active = true;
    effects = [];
    parent = null;
    run(fn){
        if(this.active){ // 如果激活
            try{
               activeEffectScope = this; // 保存activeEffectScope
               return fn();
            }finally{
               activeEffectScope = this.parent; // 还原activeEffectScope
            }
        }
    }
    stop(){
        if(this.active){
            // 创建effect的时候会将effect收集到activeEffect中
            // 调用stop时依次调用effect中的stop方法
            for (let i = 0, l = this.effects.length; i < l; i++) {
                this.effects[i].stop();
            }
            this.active = false
        }
    }
}
export function effectScope() { // 创建effectScope
    return new EffectScope();
}
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

独立effectScope

const scope = effectScope();
scope.run(()=>{
    const state = reactive({age:13});
    effect(()=>{
        console.log(state.age);
    });
    setTimeout(()=>{
        state.age++;
    },1000)
    const innerScope = effectScope(true);
    innerScope.run(()=>{
        const state = reactive({age:13});
        effect(()=>{
            console.log(state.age);
        });
        setTimeout(()=>{
            state.age++;
        },1000)
    });
});
scope.stop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
scopes = null; // 自己可以收集 effectScope
constructor(detached = false){ // 非独立的需要收集依赖
    if(!detached && activeEffectScope){ // 不是独立的就要让父亲收集effect啦~
        this.parent = activeEffectScope;
        (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this)
    }
}
if (this.scopes) { // stop时也要清理存储的effectScope
    for (let i = 0, l = this.scopes.length; i < l; i++) {
        this.scopes[i].stop()
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

Released under the MIT License.