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