ref
ref作用
将传入的数据转为响应式数据,即数据发生改变,视图同步更新
原理
ref源码分析
当声明变量,执行ref函数时,const a = ref(1),ref函数内部调用createRef函数,将传给ref函数的value传给createRef函数
export function ref<T extends object>(
value: T
): [T] extends [Ref] ? T : Ref<UnwrapRef<T>>
export function ref<T>(value: T): Ref<UnwrapRef<T>>
export function ref<T = any>(): Ref<T | undefined>
export function ref(value?: unknown) {
return createRef(value, false)
}
createRef
在createRef中,对传入的value进行类型判断,如果value是ref对象,则直接返回value,不作任何处理,否则,新建一个RefImpl对象
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
RefImpl
在该函数中可以看到,构造器的第一个参数是传入的值,第二个参数是false(判断是不是shallowRef),通过getter和setter监听value的变化,所以我们赋值的时候,要赋值给xxx.value,
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly _shallow: boolean) {
this._rawValue = _shallow ? value : toRaw(value)
this._value = _shallow ? value : toReactive(value)
}
get value() {
trackRefValue(this)
return this._value
}
set value(newVal) {
newVal = this._shallow ? newVal : toRaw(newVal)
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = this._shallow ? newVal : toReactive(newVal)
triggerRefValue(this, newVal)
}
}
}
toReactive
将传入的值进行响应式监听
export const toReactive = <T extends unknown>(value: T): T =>
isObject(value) ? reactive(value) : value
isRef
isRef作用
判断某个值是不是ref对象,返回值是true或false
原理
isRef源码分析
export function isRef<T>(r: Ref<T> | unknown): r is Ref<T>
export function isRef(r: any): r is Ref {
return Boolean(r && r.__v_isRef === true)
}
shallowRef
shallowRef作用
对传入的值的响应式监听只到value这一层,内部不会再调用toReactive函数对value对应的对象做进一步响应式监听
原理
shallowRef源码分析
与ref源码的区别在于第二个参数的值为true
export function shallowRef<T extends object>(
value: T
): T extends Ref ? T : ShallowRef<T>
export function shallowRef<T>(value: T): ShallowRef<T>
export function shallowRef<T = any>(): ShallowRef<T | undefined>
export function shallowRef(value?: unknown) {
return createRef(value, true)
}
triggerRef
triggerRef作用
该函数传入一个ref的值,由于对数据的监听深度不够(如shallowRef),ref的值发生了改变,但是有想要页面更新,可以使用triggerRef
原理
triggerRef源码分析
export function triggerRef(ref: Ref) {
triggerRefValue(ref, __DEV__ ? ref.value : void 0)
}
triggerRefValue源码
export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
ref = toRaw(ref)
if (ref.dep) {
if (__DEV__) {
triggerEffects(ref.dep, {
target: ref,
type: TriggerOpTypes.SET,
key: 'value',
newValue: newVal
})
} else {
triggerEffects(ref.dep)
}
}
}
triggerEffects源码
export function triggerEffects(
dep: Dep | ReactiveEffect[],
debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
// spread into array for stabilization
for (const effect of isArray(dep) ? dep : [...dep]) {
if (effect !== activeEffect || effect.allowRecurse) {
if (__DEV__ && effect.onTrigger) {
effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
}
if (effect.scheduler) {
effect.scheduler()
} else {
effect.run()
}
}
}
}
customRef
customRef作用
自定义自己的ref
使用案例
function myRef(value) {
return customRef(track, trigger) {
return {
get() {
track()
return value
},
set(newVal) {
value = newVal
trigger()
}
}
}
}
原理
customRef源码
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
return new CustomRefImpl(factory) as any
}
CustomRefImpl源码
class CustomRefImpl<T> {
public dep?: Dep = undefined
private readonly _get: ReturnType<CustomRefFactory<T>>['get']
private readonly _set: ReturnType<CustomRefFactory<T>>['set']
public readonly __v_isRef = true
constructor(factory: CustomRefFactory<T>) {
const { get, set } = factory(
() => trackRefValue(this),
() => triggerRefValue(this)
)
this._get = get
this._set = set
}
get value() {
return this._get()
}
set value(newVal) {
this._set(newVal)
}
}