toRef、toRefs、toRaw

1,093 阅读1分钟

toRef、toRefs

作用

主要用于对响应式对象的结构,即:

  1. 在不丢失响应式的情况下对对象进行解构
  2. 针对的是响应式对象,不是普通对象
  3. 是响应式的延续,不创造新的响应式

使用

修改nameRef的value值时,obj的值也会发生改变

const obj = reactive({
    name: '张三',
    age: 18
})
const nameRef = toRef(obj, 'name')
const { name, age } = toRefs(obj)
nameRef.value = '李四'

原理

toRef

与ref的区别在于,ref底层调用了RefImpl,toRef底层调用了ObjectRefImpl

export function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K
): ToRef<T[K]>

export function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K,
  defaultValue: T[K]
): ToRef<Exclude<T[K], undefined>>

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)
}

toRefs

与toRef的区别在于对传入的对象的所有的属性进行了处理

export type ToRefs<T = any> = {
  [K in keyof T]: ToRef<T[K]>
}
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
}

ObjectRefImpl

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
  }
}

toRaw

作用

传入一个响应式对象,返回该响应式对象对应的普通对象

使用

obj与state互不干扰

const obj = reactive({
  bar: 0
})
const state = toRaw(obj) // state {bar: 0}

原理

toRaw

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