一、ref
普通值变成响应式 就需要使用 ref
原理:将普通类型转化成一个对象,这个对象中有 value 属性, 指向原来的值。
 
ref 和 reactive 的区别: reactive 内部采用 proxy,ref 内部使用的是 defineProperty
//将普通类型变成一个对象export function ref(value?: unknown) {return createRef(value) // vue 源码基本上都是高阶函数,做了类似柯里化的功能}function createRef(rawValue: unknown, shallow = false) {if (isRef(rawValue)) {return rawValue}// 返回一个类return new RefImpl(rawValue, shallow)}// 如果是对象就调用 reactive 转成响应式的,否则直接返回const convert = <T extends unknown>(val: T): T =>isObject(val) ? reactive(val) : val// 这个类的底层实现就是 definepropertyclass RefImpl<T> {private _value: T // 声明了才能在下面用,不声明使用会报错 ,声明但没有赋值public readonly __v_isRef = trueconstructor(private _rawValue: T, public readonly _shallow: boolean) { // 参数前面加 private public修饰符 表示此属性放到了实例上this._value = _shallow ? _rawValue : convert(_rawValue)}// 类的属性访问器get value() {track(toRaw(this), TrackOpTypes.GET, 'value')return this._value // 取值取value,会代理到 _value 上}set value(newVal) {// 判断新值和老值是否有变化if (hasChanged(toRaw(newVal), this._rawValue)) {this._rawValue = newVal // 新值会作为老值this._value = this._shallow ? newVal : convert(newVal) // 如果是深度需要把这个对象全部转成响应式的trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)}}}
二、toRef
toRef 将一个对象中的某一个属性转换成 ref

class ObjectRefImpl<T extends object, K extends keyof T> {public readonly __v_isRef = trueconstructor(private readonly _object: T, private readonly _key: K) {}get value() {return this._object[this._key]}set value(newVal) {this._object[this._key] = newVal}}// 将一个 key 对应的值转换成 refexport function toRef<T extends object, K extends keyof T>(object: T, // 目标对象key: K // key 属性): ToRef<T[K]> {return isRef(object[key])? object[key]: (new ObjectRefImpl(object, key) as any)}
三、toRefs
将一个对象中的多个属性转成 ref 
// 循环调用 toRefexport 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}
使用场景
toRef 和 toRefs 相当于响应式解构 ,解构某一个就使用 toRef ,解构多个使用 toRefs。
