【vue3源码】十、响应式API中的工具函数

参考代码版本:vue 3.2.37

官网文档:https://vuejs.org/

isRef

export function isRef(r: any): r is Ref {  return !!(r && r.__v_isRef === true)}

通过对象中是否存在__v_isRef属性并且__v_isRef对应值为true来判断是否为ref

unref

export function unref<T>(ref: T | Ref<T>): T {  return isRef(ref) ? (ref.value as any) : ref}

如果是ref则返回ref.value,否则间接返回ref

toRef

export function toRef<T extends object, K extends keyof T>(  object: T,  key: K,  defaultValue?: T[K]): ToRef<T[K]> {  const val = object[key]  return isRef(val)    ? val    : (new ObjectRefImpl(object, key, defaultValue) as any)}

toRef接管三个参数:object待转换的对象、key待转换的keydefaultValue默认值。

如果object[key]ref,则间接返回object[key]。否则返回一个ObjectRefImpl实例。

class ObjectRefImpl<T extends object, K extends keyof T> {  public readonly __v_isRef = true  constructor(    private readonly _object: T,    private readonly _key: K,    private readonly _defaultValue?: T[K]  ) {}  get value() {    const val = this._object[this._key]    return val === undefined ? (this._defaultValue as T[K]) : val  }  set value(newVal) {    this._object[this._key] = newVal  }}

ObjectRefImpl结构器中会别离将objectkeydefaultValue保留至本人的公有属性中,当获取ObjectRefImpl实例的value属性时,会从this._object中获取数据,因为this._object和原来的object内存地址是统一的,所以这和间接应用object获取key获取数据没有区别,只不过通过toRef转换之后,能够和ref那样,通过value属性进行取值、设值。

toRefs

export function toRefs<T extends object>(object: T): ToRefs<T> {  if (__DEV__ && !isProxy(object)) {    console.warn(`toRefs() expects a reactive object but received a plain one.`)  }  const ret: any = isArray(object) ? new Array(object.length) : {}  for (const key in object) {    ret[key] = toRef(object, key)  }  return ret}

toRefs中会申明一个新的对象或数组,而后遍历objectkey值,并调用toRef,将后果存入新的对象或数组中,最初返回这个新的对象或数组。

isReactive

export function isReactive(value: unknown): boolean {  if (isReadonly(value)) {    return isReactive((value as Target)[ReactiveFlags.RAW])  }  return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE])}

如果value是只读的,那么就对valueReactiveFlags.RAW属性持续调用isReactive;否则依据valueReactiveFlags.IS_REACTIVE属性判断是否为reactive

isReadonly

export function isReadonly(value: unknown): boolean {  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])}

通过valueReactiveFlags.IS_READONLY属性判断是否只读。

isProxy

isProxy是用来判断value是否为reactivereadonly,并不是用来判断valueproxy类型的

export function isProxy(value: unknown): boolean {  return isReactive(value) || isReadonly(value)}

toRaw

获取传入对象的原始对象。

export function toRaw<T>(observed: T): T {  const raw = observed && (observed as Target)[ReactiveFlags.RAW]  return raw ? toRaw(raw) : observed}

observedReactiveFlags.RAW属性能够返回对象的原始对象,但这个原始对象有可能也是能够响应式对象(如readonly(reactive(obj))),所以递归调用toRaw,以获取真正的原始对象。

markRaw

将对象标记为永远不能转为reactive对象。

export function markRaw<T extends object>(  value: T): T & { [RawSymbol]?: true } {  def(value, ReactiveFlags.SKIP, true)  return value}

通过Object.definePropertyvalueReactiveFlags.SKIP(不会被遍历)属性标记为true。当尝试创立reactive时,会查看该值。