Refs API的原理
ref
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value。
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
ref 与 reactive 最大的区别在于,reactive的参数只能是对象,但 ref 可以是任意类型
ref对象属性
ref的参数如果是一个对象的话,会转换为 reactive ,reactive 会进行深度转换把所有对象元素都转换为reactive。
const a = ref({});
console.log(isReactive(a.value)); // true
const b = ref({ c : {} });
console.log(isReactive(b.value.c)); // true
ref初始化
const a = ref(1);
/**
* @param {any} ref实参 1
* @param {Boolean} 对象元素是否转为 reactive false
*/
function ref(value?: unknown) {
return createRef(value)
}
function createRef(rawValue: unknown, shallow = false) {
if (isRef(rawValue)) {
return rawValue
}
// rawValue:1
// shallow:false
return new RefImpl(rawValue, shallow)
}
shallowRef
创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的。
不想要深度响应式的 reactive 就可以使用 shallowRef
const a = ref({})
isReactive(a.value) // true
const b = shallowRef({})
isReactive(b.value) // false
const a = shallowRef(1);
function shallowRef(value?: unknown) {
return createRef(value, true)
}
function createRef(rawValue: unknown, shallow = false) {
if (isRef(rawValue)) {
return rawValue
}
// rawValue:1
// shallow:true
return new RefImpl(rawValue, shallow)
}
RefImpl
class RefImpl<T> {
私有变量 _value用来保存传入参数
private _value: T
公用只读变量 __v_isRef标记对象为 ref
public readonly __v_isRef = true
constructor(private _rawValue: T, public readonly _shallow = false) {
// 如果_rawValue是对象,将其转为 reactive 响应式对象。它的所有对象元素都会转化为 reactive 响应式对象
// shallowRef就不会将元素转化为 reactive 响应式对象。
this._value = _shallow ? _rawValue : isObject(_rawValue) ? reactive(_rawValue) : _rawValue
}
// get value时收集依赖
get value() {
track(toRaw(this), TrackOpTypes.GET, 'value')
return this._value
}
// get value时收集依赖
set value(newVal) {
// newVal不为_rawValue时,修改value
if (hasChanged(toRaw(newVal), this._rawValue)) {
// _rawValue 和 _value 的区别在于
// _value 保存的可能是转化的 reactive 响应式对象
// _rawValue 保存的是实参数据
this._rawValue = newVal
this._value = this._shallow ? newVal : isObject(newVal) ? reactive(newVal) : newVal
trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)
}
}
}
const count = ref({ a: 1 })
ref 返回的就是一个对象。ref 与 shallowRef 的区别在于 对象属性 是否转为 reactive 响应式对象
isRef
检查值是否为一个 ref 对象。
function isRef(r: any): r is Ref {
return Boolean(r && r.__v_isRef === true)
}
判断 __v_isRef 属性是不是true就行。如果你 let a = { __v_isRef : true },也是可以过isRef的。
unref
如果参数是一个 ref,则返回内部值,否则返回参数本身。
function unref<T>(ref: T | Ref<T>): T {
return isRef(ref) ? ref.value : ref
}
let a = { __v_isRef: true, value: 1111 };
console.log(isRef(a)) => true
console.log(unref(a)) => 111
toRef
可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
function toRef(object,key){
// 如果已经是一个ref,直接返回
return isRef(object[key])
? object[key]
: (new ObjectRefImpl(object, key) as any)
}
ObjectRefImpl
class ObjectRefImpl<T extends object, K extends keyof T> {
public readonly __v_isRef = true
constructor(private readonly _object: T, private readonly _key: K) {}
get value() {
return this._object[this._key]
}
set value(newVal) {
this._object[this._key] = newVal
}
}
const a = reactive({ foo: 1, bar: 2 })
const b = toRef(state, 'foo')
b.value = 2
// this._object[this._key] = newVal
// a[foo] = 2
console.log(a.foo) // 2
a.foo = 3
console.log(b.value) // 3
// return this._object[this._key]
// return a[foo]
简简单单就是个代理
toRefs
function toRefs(object){
const ret: any = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
ret[key] = toRef(object, key)
}
return ret
}
遍历一遍,用toRef