Reference Documents:
- Vue3 official document
- Vue – next to the source code
ref
Takes an internal value and returns a reactive and mutable REF object. The ref object has a single property.value pointing to an internal value.
const count = ref(0)
console.log(count.value) / / 0
count.value++
console.log(count.value) / / 1
Copy the code
Implementation principle of REF
The principle of a ref is to convert a common value into an object, and to add dependency collection and trigger updates to get and set values
function ref(value){
return createRef(value)
}
function convert(rawValue){
return isObject(rawValue) ? reactive(rawValue) : rawValue
}
function createRef(value, shallow = false){
return new RefImpl(value, shallow)
}
class RefImpl{
_value;
__v_isRef = true // flag means this is a ref
constructor(rawValue,shallow){
this.rawValue = rawValue;
this.shallow = shallow;
this._value = shallow ? rawValue : convert(rawValue)
}
get value() {// Collect dependencies when setting values
track(this.'get'.'value')
return this._value
}
set(newValue){
if(hasChange(newValue, this.rawValue)){
this.rawValue = newValue;
this._value = this.shallow ? newValue : convert(newValue)
// Dependency updates are triggered when setting the value
trigger(this.'set'.'value', newValue)
}
}
}
Copy the code
unref
If the argument is a ref, the internal value is returned, otherwise the argument itself is returned. This is val = isRef(val), right? Val. value: The syntactic sugar function of val
function useFoo(x: number | Ref<number>) {
const unwrapped = unref(x) // Unwrapped must now be a numeric type
}
Copy the code
toRef
Can be used to create a new REF for a property on a source responsive object. The REF can then be passed, maintaining a reactive connection to its source property.
const state = reactive({
foo: 1.bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) / / 2
state.foo++
console.log(fooRef.value) / / 3
Copy the code
ToRef is useful when you want to pass a prop ref to a composite function:
export default {
setup(props) {
useSomeFeature(toRef(props, 'foo'))}}Copy the code
ToRef returns an available REF even if the source property does not exist. This makes it especially useful when using optional prop, which is not handled by toRefs.
ToRef implementation principle
ToRef can only convert an attribute of a reactive object to a REF, a normal object. There is no reactive because it does a proxy mapping to the source object and does not collect dependencies or trigger updates.
class ObjectRefImpl {
__v_isRef = true;
constructor(target, key) {
this.target = target;
this.key = key
}
get value() {
return this.target[this.key];
}
set value(newValue) {
this.target[this.key] = newValue
}
}
function toRef(target, key) {
return isRef(object[key]) ? object[key] : new ObjectRefImpl(target, key)
}
Copy the code
toRefs
Converts a reactive object to a normal object, where each property of the resulting object is a REF pointing to the corresponding property of the original object.
const state = reactive({
foo: 1.bar: 2
})
const stateAsRefs = toRefs(state)
/* stateAsRefs type: {foo: Ref
, bar: Ref
} */
// the ref and the original property are "linked"
state.foo++
console.log(stateAsRefs.foo.value) / / 2
stateAsRefs.foo.value++
console.log(state.foo) / / 3
Copy the code
ToRefs implementation principle
ToRefs converts all attribute values of a reactive object to a ref
function toRefs() {
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
}
Copy the code