toRef、toRefs
作用
主要用于对响应式对象的结构,即:
- 在不丢失响应式的情况下对对象进行解构
- 针对的是响应式对象,不是普通对象
- 是响应式的延续,不创造新的响应式
使用
修改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
}