手摸手学习vue3源码四:toRefs

55 阅读1分钟
  • 文件目录:packages/reactivity/src/ref.ts
  • 核心函数:ObjectRefImpl
  • 作用:将响应式对象转换为普通对象,普通对象的每个属性都是指向源对象的响应属性的 ref。每个单独的ref都是通过 toRef 创建的
  • 源码解析
export function toRefs(object) {
    // 不是响应式数据,警告
    if (__DEV__ && !isProxy(object) {
        warn()
    }
    const ret = isArray(object) ? new Array(object.length) : {}
    for(const key in object) {
        ret[key] = propertyToRef(object, key)
    }
    return ret
}
// 处理源对象属性值为ref, 如果是ref对象,直接返回;否则,创建 ref 对象
function propertyToRef(source, key, defaultValue) {
    const val = source[key]
    return isRef(val) ? val : (new ObjectRefImpl(source, key, defaultValue) as any)
}
  • 使用
const user = reactive({ name: "zhangsan", age: 16, sex: "男" });
const userToRefs = toRefs(user);

user.age++
// 此时,userToRefs中的源属性已经链接上了
console.log(userToRefs.age) // Ref<17> age是Ref对象,需要.value获取值

userToRefs.age.value++;
console.log(user.age); 18
const { age } = userToRefs;
console.log("解构:", age); // Ref<18>

敲重点

  • toRefs 在组合式函数中,返回响应式对象时,会非常有用,解构/展开返回的对象,不会失去响应式
function testToRefs() {
    const state = reactive({
        foo: 1, 
        bar: 2
    })
    
    return toRefs(state)
}

console.log("解构:", testToRefs());
const { foo, bar } = testToRefs();
console.log("解构的值:", foo, bar); // Ref<foo> Ref<bar> 解构的值不会失去响应式
  • toRefs 在调用时,只会为源对象上可以枚举的属性创建 Ref。如果要为可能不存在的属性创建,需使用 toRef