More articles
preface
Reactive was introduced in the previous article, and this article introduces the REF-related apis
Simplify the code
Vue3-ref source location
class
Reactive is a Proxy, and ref is a class reactive
ref
Source code implementation:
export function ref(value? : unknown) {
return createRef(value, false)}function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
Copy the code
Vue returns a RefImpl via createRef. RefImpl is a class
class RefImpl<T> {
private _value: T
private _rawValue: T
publicdep? : Dep =undefined
public readonly __v_isRef = true
constructor(value: T, public readonly _shallow: boolean) {
this._rawValue = _shallow ? value : toRaw(value)
this._value = _shallow ? value : convert(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 : convert(newVal)
triggerRefValue(this, newVal)
}
}
}
Copy the code
Get returns this._value. By default, convert is used to retrieve real data
const convert = <T extends unknown>(val: T): T => isObject(val) ? reactive(val) : val
Copy the code
RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl: RefImpl
// If the object is reactive
const convert = val= > isObject(val) ? reactive(val) : val
class RefImpl {
constructor(value, shallow) {
this.__v_isRef = true
this._rawValue = shallow ? value : toRaw(value)
this._value = shallow ? value : convert(value)
this._shallow = shallow
}
get value() {
return this._value
}
set value(newValue) {
newValue = this._shallow ? newValue : toRaw(newValue)
if(hasChanged(newValue, this._rawValue)) {
this._rawValue = newValue;
this._value = this._shallow ? newValue : convert(newValue)
}
}
}
function createRef(value, shallow) {
if(isRef(value)) return value
return new RefImpl(value, shallow);
}
function ref(value) {
return createRef(value, false)}Copy the code
isRef
RefImpl has a read-only __v_isRef attribute, which is used to determine whether it is ref
function isRef(r) {
return r && r.__v_isRef === true
}
Copy the code
unref
If the parameter is a ref, the internal value is returned, otherwise the parameter itself is returned
function unref(ref) {
return isRef(ref) ? ref.value : ref
}
Copy the code
toRef
The toRef implementation also manipulates the source object by manipulating the value attribute through the set and GET methods of the custom class
class ObjectRefImpl {
constructor(_object, _key) {
this.__v_isRef = true
this._object = _object
this._key = _key
}
get value() {
// Get reactive
return this._object[this._key]
}
set value(newVal) {
// Set reactive
this._object[this._key] = newVal
}
}
function toRef(target, key) {
const value = target[key]
return isRef(value) ? value : new ObjectRefImpl(target, key)
}
Copy the code
toRefs
ToRefs is an operation on a reactive object with the help of a toRef
function toRefs(object) {
if(! isProxy(object)) {console.warn(`toRefs() expects a reactive object but received a plain one.`)}const ret = isArray(object) ? new Array(object.length) : {}
for (const key in object) {
ret[key] = toRef(object, key)
}
return ret
}
Copy the code
shallowRef
ShallowRef will follow the change of ref, but will not make. Value reactive. Shallow is set to true, and ref will not go convert if it is an object
function shallowRef(value) {
return createRef(value, true)}Copy the code
customRef
CustomRef receives a factory function that returns custom GET and set methods. The custom GET and SET methods are called when fetching and assigning values, respectively. There is no data collection involved here, just a simple logical implementation
class CustomRefImpl {
constructor(factory) {
const { get, set } = factory()
this._get = get
this._set = set
}
get value() {
return this._get()
}
set value(newValue) {
this._set(newValue)
}
}
function customRef(factory) {
return new CustomRefImpl(factory)
}
Copy the code
conclusion
This look at the source code to write unexpected harvest