当前位置: 首页 > Web前端 > HTML

【vue3源码】10.响应式API中的工具函数

时间:2023-03-28 16:43:45 HTML

【vue3源码】10.响应式API中的工具函数参考代码版本:vue3.2.37官方文档:https://vuejs.org/isRefexportfunctionisRef(r:any):risRef{return!!(r&&r.__v_isRef===true)}通过对象中是否存在__v_isRef属性且__v_isRef对应的值为true来判断是否为ref。unrefexport函数unref(ref:T|Ref):T{returnisRef(ref)?(ref.valueasany):ref}如果是ref,返回ref.value,否则直接返回reftoRefexport函数toRef(object:T,key:K,defaultValue?:T[K]):ToRef{constval=object[key]returnisRef(val)?val:(newObjectRefImpl(object,key,defaultValue)asany)}toRef接收三个参数:待转换的对象、待转换为key的key、defaultValue默认值。如果object[key]为ref,则直接返回object[key]。否则返回一个ObjectRefImpl实例。classObjectRefImpl{publicreadonly__v_isRef=trueconstructor(privatereadonly_object:T,privatereadonly_key:K,privatereadonly_defaultValue?:T[K]){}getvalue(){constval=this._object[this._key]返回val===未定义?(this._defaultValueasT[K]):val}setvalue(newVal){this._object[this._key]=newVal}}在ObjectRefImpl中,构造函数会将对象、键和默认值保存在自己的私有属性中。在获取ObjectRefImpl实例的value属性时,会从this._object中获取数据,因为this._object的内存地址和原来的object是一致的,所以这和直接使用object获取key没什么区别获取数据,但是经过toRef转换后,可以像ref一样通过value属性获取和设置值。toRefsexport函数toRefs(object:T):ToRefs{if(__DEV__&&!isProxy(object)){console.warn(`toRefs()需要一个反应对象,但收到一个普通对象。`)}constret:any=isArray(object)?newArray(object.length):{}for(constkeyinobject){ret[key]=toRef(object,key)}returnret}toRefs会声明一个新的对象或数组,然后遍历对象的key值,并调用toRef,将结果存入一个新的对象或数组,最后返回新的对象或数组。isReactiveexport函数isReactive(value:unknown):boolean{if(isReadonly(value)){returnisReactive((valueasTarget)[ReactiveFlags.RAW])}return!!(value&&(valueasTarget)[ReactiveFlags.IS_REACTIVE])}如果该值是只读的,则继续对该值的ReactiveFlags.RAW属性调用isReactive;否则根据value的ReactiveFlags.IS_REACTIVE属性判断是否响应。isReadonlyexportfunctionisReadonly(value:unknown):boolean{return!!(value&&(valueasTarget)[ReactiveFlags.IS_READONLY])}通过value的ReactiveFlags.IS_READONLY属性判断是否只读。isProxyisProxy用于判断该值是reactive还是readonly,不判断该值是否是代理类型exportfunctionisProxy(value:unknown):boolean{returnisReactive(value)||isReadonly(value)}toRaw获取原始对象的传入对象。导出函数toRaw(observed:T):T{constraw=observed&&(observedasTarget)[ReactiveFlags.RAW]returnraw?toRaw(raw):observed}被观察到的ReactiveFlags.RAW属性可以返回原始object对象,但是这个原始对象也可能是响应式对象(比如readonly(reactive(obj))),所以递归调用toRaw得到真正的原始对象。markRaw将对象标记为永不响应。exportfunctionmarkRaw(value:T):T&{[RawSymbol]?:true}{def(value,ReactiveFlags.SKIP,true)returnvalue}通过Object.defineProperty(不会被遍历)属性被标记为真。尝试创建反应式时会检查此值。