“This is the 21st day of my participation in the First Challenge 2022. For details: First Challenge 2022.”
preface
Through the learning of reactive source code and single step debugging, Vue3.0 reactive principle is understood, which uses the Proxy getter to collect data dependent DEP. This dependency is actually the component update function activeEffect, and then triggers the component update function in the setter to achieve the reactive effect. This article will learn another reactive API ref source
ref
Ref documents and Reactive documents can both convert data to reactive. The difference is that ref takes an internal value and returns a reactive copy of the object, and reactive normally uses a single value in ref and an object in Reactive. But you can also use objects in a REF
Source code analysis
CTRL + T to find ref()
ref
Function of positionpackages\reactivity\src\ref.ts
You can see there are multiple of themref
The type definition of a function
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>
Copy the code
- So there are two ways you can constrain types in normal development using typeScript
const numberData = ref<number>(1)
const stringData: Ref<string> = ref(' ')
Copy the code
ref
The function returns onecreateRef
The function passes in the data we defined and adds a second argumentfalse
export function ref(value? : unknown) {
return createRef(value, false)}Copy the code
createRef
The function returns oneRefImpl
Class, and pass in its own arguments intact
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
Copy the code
RefImpl
ifconstructor
The second argument toshallow
是true
I don’t convert to responsive data beforeref
The second argument passed in is obviouslyfalse
So it’s going to be responsive datatoReactive
And then on the incomingvalue
forget
和set
The operation is therefore in useref
Need to use.vaule
class RefImpl<T> { private _value: T private _rawValue: T public dep? : Dep =undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
this._rawValue = __v_isShallow ? value : toRaw(value)
// Use toReactive recursively
this._value = __v_isShallow ? value : toReactive(value)
}
get value() {
trackRefValue(this)
return this._value
}
set value(newVal) {
newVal = this.__v_isShallow ? newVal : toRaw(newVal)
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = this.__v_isShallow ? newVal : toReactive(newVal)
// Trigger side effects
triggerRefValue(this, newVal)
}
}
}
Copy the code
- You can look at it here
toReactive
Function, will determineref
Is called if it is an object typereactive
Delta function, soref
Object type data can also be used in
export const toReactive = <T extends unknown>(value: T): T =>
isObject(value) ? reactive(value) : value
Copy the code
get
Will wrap a layer before returning datatrackRefValue
The key is data dependencedep
The collection is then triggeredtrackEffects
Tracking rely on
export function trackRefValue(ref: RefBase<any>) {
if (isTracking()) {
ref = toRaw(ref)
// Create a dependency for the Ref instance
if(! ref.dep) {// A Set composed by RectiveEffect
ref.dep = createDep()
}
if (__DEV__) {
trackEffects(ref.dep, {
target: ref,
type: TrackOpTypes.GET,
key: 'value'})}else {
// Rely on collection
trackEffects(ref.dep)
}
}
}
Copy the code
set
Is executed when the new value is settriggerRefValue
Function, and triggers the side effect functiontriggerEffects
export function triggerRefValue(ref: RefBase
, 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)
}
}
}
Copy the code
- So we’ll see what happens here
get
和set
Do things andreactive
It’s the same thing