Reactive and REF are used, but I won’t go into the basic usage.

However, if reacive nested refs, something counterintuitive happens.

Example 1

{
  template: '<div>{{observeA.a}}</div>'.setup() {
    const observeA = Vue.reactive({a: Vue.ref(1)})
    // Q: How do I change a variable to trigger a view update?
    // 答: ...
    return {
      observeA,
    }
  }
}
Copy the code
Look at the answer

A: observea. a = 3

You might guess observea.a.value = 3. But this is not going to work.

Example 2

{
  template: '<div>{{observeA[0]}}</div>'.setup() {
    const observeA = Vue.reactive([Vue.ref(1)])
    return {
      observeA,
    }
  }
}
// Ask: what is the page display?
// 答: ...
Copy the code
Look at the answer

A: {" _rawValue ": 1," _shallow ": false," __v_isRef ": true," _value ": 1}



{{observeA[0].value}}

You thought it was one?

Example 3

// Combine example 1 and example 2
{
  template: '<div>{{observeA[0].value}}</div>'.setup() {
    const observeA = Vue.reactive([ Vue.ref(1)])// ask: How do I trigger view updates
    // 答: ...
    return {
      observeA,
    }
  }
}
Copy the code
Look at the answer

Answer: observeA[0]. Value = 3


Very good. Whether you have succeeded or not is unclear to this circle

parsing

Some people ask, what’s going on? This is a blind test. It’s a blind test. I said this wasn’t a random test. I came prepared.

Examples 1 and 3

Why update ref without.value? Let’s look at the source code of reactive/SRC/baseHandlers 139 ~ 142.

if(! isArray(target) && isRef(oldValue) && ! isRef(value)) { oldValue.value = valuereturn true
}
/ /! isArray(target); Reactive update target is not an array
// isRef(oldValue); The value to be updated is a ref object
/ /! isRef(value); The value to be updated is not a REF object
Copy the code
// Example 1
const observeA = Vue.reactive({a: Vue.ref(1)})
observeA.a = 3! isArray({a: Vue.ref(1)})  // true 
isRef(Vue.ref(1))          // true! isRef(3)                  // true
Copy the code

Similarly, target 3 cannot be updated directly because it is an array.

Example 2:

RefImpl (reactive

) ¶ RefImpl (reactive

) ¶
[]>
[]>

Continue to look at the source code of reactive/SRC/baseHandlers 109 ~ 113.

function createGetter(isReadonly = false, shallow = false) {
  // ...
  if (isRef(res)) {
    // ref unwrapping - does not apply for Array + integer key.
    constshouldUnwrap = ! targetIsArray || ! isIntegerKey(key)return shouldUnwrap ? res.value : res
  }
  // ...
}
Copy the code

As you can see, this logic is in the createGetter function. That’s the getter handler for the Proxy. The value res that you get for the target is the ref object. When target is not an array, or key is not an integer, it is automatically expanded for you, that is, without.value.

  // Review example 2
  <div>{{observeA[0]}}</div>
  const observeA = Vue.reactive([ Vue.ref(1)])// There is no value here because value is a getter, so after serialization only the instance property of class RefImpl is left
  // _value is a private value inside class RefImpl
  observeA[0] // { "_rawValue": 1, "_shallow": false, "__v_isRef": true, "_value": 1 }! isArray(observeA)// false! isIntegerKey(0)   // false
  shouldUnwrap      // false
Copy the code

Return res.value. The result is expected, but there must be a reason not to write this. I have only just read the source code of createApp and Reactive modules. Maybe we’ll see why. Keep it up