当前位置: 首页 > Web前端 > vue.js

【vue3源码】三、EffectScope源码分析

时间:2023-03-31 18:33:50 vue.js

前言参考代码版本:vue3.2.37官方文档:https://vuejs.org/关于为什么需要effectScope,可以参考RFC使用示例。EffectScope可以用于内部响应对象的副作用的统一管理。constcounter=ref(1)constscope=effectScope()scope.run(()=>{constdoubled=computed(()=>counter.value*2)watch(doubled,()=>console.log(doubled.value))watchEffect(()=>console.log('Count:',doubled.value))})//处理当前范围内的所有effectscope.stop()。effectScope接收一个boolean值,如果传入true,在free模式下,创建的scope不会被父scope回收。一般来说,如果是free模式,scope之间没有父子关系,每个scope都是独立的。exportfunctioneffectScope(detached?:boolean){returnnewEffectScope(detached)}effectScope返回一个EffectScope实例。EffectScopeexport类EffectScope{active=trueeffects:ReactiveEffect[]=[]cleanups:(()=>void)[]=[]parent:EffectScope|未定义范围:EffectScope[]|undefined/***跟踪子作用域在其父作用域数组中的索引以优化*删除*/privateindex:number|undefinedconstructor(detached=false){if(!detached&&activeEffectScope){this.parent=activeEffectScopethis.index=(activeEffectScope.scopes||(activeEffectScope.scopes=[])).push(this)-1}}运行(fn:()=>T):T|undefined{if(this.active){try{activeEffectScope=thisreturnfn()}finally{activeEffectScope=this.parent}}elseif(__DEV__){warn(`无法运行非活动效果范围。`)}}on(){activeEffectScope=this}off(){activeEffectScope=this.parent}stop(fromParent?:boolean){if(this.active){leti,lfor(i=0,l=this.effects.length;i(fn:()=>T):T|undefined{if(this.active){try{activeEffectScope=thisreturnfn()}finally{activeEffectScope=this.parent}}elseif(__DEV__){warn(`cannotrunaninactiveeffectscope.`)}}run方法会先判断this.active,如果this.active为真,即EffectScope是active的,那么this会赋值给activeEffectScope,然后fn就会被执行,并返回其执行结果。fn执行时,将activeEffectScope改为this.parent。onon(){activeEffectScope=this}on方法会将activeEffectScope指向当前的EffectScope实例。offoff(){activeEffectScope=this.parent}off方法会将activeEffectScope指向当前EffectScope实例的父作用域。stopstop函数的作用是清除作用域内的所有响应效果,包括子作用域。stop接收一个布尔值fromParent参数,如果fromParent为真,stop将不会删除父作用域中的引用。stop(fromParent?:boolean){if(this.active){leti,l//调用ReactiveEffect.prototype.stop清除范围内的所有反应效果for(i=0,l=this.effects.length;ivoid){if(activeEffectScope){activeEffectScope.cleanups.push(fn)}elseif(__DEV__){warn(`onScopeDispose()在没有活动效果范围时被调用`+`要关联。`)}}如果scopes属性存在于当前作用域中,说明当前作用域有子作用域,需要销毁所有子作用域。if(this.scopes){for(i=0,l=this.scopes.length;i