Why is vue3 reactive value not recommended to deconstruct && analyze responsive structure

The book continues above, we continue to discuss this topic, I still leave the screenshot of the official website here.

image.png

problem thinking

  1. The deconstructed value is a basic data type and will lose the responsiveness. If it is a reference data type, will it remain responsive?
  2. Is Lost Responsive doing it for us vueinternally ?

problem inquiry

Let's write an example first to construct the scene, which is relatively simple.

<script setup>
import { reactive } from "vue";

const state = reactive({
  obj: {
    name: "zhangsan",
  },
});

const handleClick = () => {
  const { obj } = state;
  obj.name = "lisi";
};
</script>
<template>
  <button @click="handleClick">点击切换</button>
  <div>{{ state }}</div>
</template>
复制代码

The effect is as follows:

snapshot.gif

Let's modify the code below:

const handleClick = () => {
  const { name } = state.obj;
  name = "lisi";
};
复制代码

The effect is as follows:

snapshot (1).gif

After the above comparison, it is found that when the deconstructed is a reference object type, it is responsive, and when the basic data type is used, the responsiveness will be lost.

Source code analysis

image.png

We put debug on the top code, and then we enter the reactivemethod , it receives one target, and then judges whether it is read-only, and finally returns the return value of the createReactiveObjectmethod call, and we enter this method.

image.png

In this method, some judgments are made, first to judge whether it is an object, if not, return the value.

Then judge whether the identity __v_rawis already a proxied object, and if so, return it.

The next judgment is that if existingProxythe proxy has been Proxy, proxyMapthe Proxy object is directly taken out from the data structure, which is a way to improve performance. It can be seen from the code that the Proxy object will be proxyMap.set(target, proxy)operated , and the proxyMapcall here is WeakMapthe instance of .

Then go down, and then add a whitelist to the objects that can be reactive. Only Object, Array, Map, Set, WeakMap, and WeakSet objects can be reactive.

image.png

Finally, Proxy is performed, and only the first layer is Proxy when reactive for the first time. Let's look at the Proxy object after reactive

image.png

At this time, the targetTypevalue is 1, so it will go baseHandlers. This method createReactiveObjectis the third parameter of the input parameter, that is mutableHandlers, it contains the common methods of Proxy

image.png

createGetterIt is the function executed after calling the getmethod . In line 447, we found that if the child item is still an object, it will recursively call reactiveto perform a deep proxy. At this point, we found that the source code did not do anything to the lost response, that is to say, it lost Reactivity is not in Vue but in the Proxy object itself.

image.png

Simple implementation

const obj = {
    count: 1
};
const proxy = new Proxy(obj, {
    get(target, key) {
        console.log("get");
        return target[key]
    },
    set(target, key, value) {
        console.log("set");
        target[key] = value
        return true;
    }
});
console.log(proxy.count);
复制代码

When we try to read the value, the getmethod , and when the value is set, the setmethod will be called. If let { count } = proxy; count = 2destructuring and reassignment will not trigger setthe method call. Then if the destructuring is a reference data type, now let's change the above code:

const obj = {
  counter: {
    count: 1
  }
};
const reactive = (target) => {
  return new Proxy(obj, {
    get(target, key) {
      console.log("get");
      if (typeof target[key] === 'object') {
        return reactive(target[key]);
      }
      return target[key]
    },
    set(target, key, value) {
      console.log("set");
      target[key] = value
      return true;
    }
  });
}
let {
  counter
} = reactive(obj);
counter.count = 2
复制代码

At this time, both getmethods and setmethods will be called, which also confirms our above conclusion,

Guess you like

Origin juejin.im/post/7080127118486552584