vue3 반응 값이 반응 구조를 분해 및 분석하는 데 권장되지 않는 이유

책은 위에서 계속되고, 우리는 이 주제에 대해 계속 논의하고, 나는 여전히 공식 웹사이트의 스크린샷을 여기에 남겨둡니다.

이미지.png

문제 사고

  1. 분해된 값은 기본 데이터 유형으로 응답성을 잃게 되는데, 참조 데이터 유형이면 응답성을 유지합니까?
  2. Lost Responsive는 vue내부적 있습니까?

문제 문의

상대적으로 간단한 장면을 구성하기 위해 먼저 예제를 작성해 보겠습니다.

<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>
复制代码

효과는 다음과 같습니다.

스냅샷.gif

아래 코드를 수정해 보겠습니다.

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

효과는 다음과 같습니다.

스냅샷 (1).gif

위의 비교 결과, deconstructed가 참조 객체 타입일 경우 반응형이며, 기본 데이터 타입을 사용할 경우 반응형이 상실되는 것을 알 수 있다.

소스 코드 분석

이미지.png

최상위 코드에 디버그를 넣고 reactive메소드 하나 target를 수신한 다음 읽기 전용인지 판단하고 마지막으로 createReactiveObject메소드 이 메소드를 입력합니다.

이미지.png

이 방법은 어떤 판단을 하여 먼저 객체인지 아닌지를 판단하고, 그렇지 않다면 값을 반환합니다.

그런 다음 ID __v_raw가 하고, 그렇다면 반환합니다.

다음 판단 existingProxyproxyMapProxy 객체를 데이터 구조에서 직접 빼내어 성능을 향상시키는 방법이라는 것입니다. Proxy 객체는 나중에 proxyMap.set(target, proxy)동작 , proxyMap여기서 호출하는 것은 WeakMap의 인스턴스이다.

그런 다음 아래로 이동하여 반응할 수 있는 개체에 화이트리스트를 추가합니다.Object, Array, Map, Set, WeakMap 및 WeakSet 개체만 반응할 수 있습니다.

이미지.png

마지막으로 Proxy가 수행되며 처음 반응할 때 첫 번째 레이어만 Proxy입니다. Reactive 후 Proxy 객체를 살펴보겠습니다.

이미지.png

이 때 targetType값 은 1이므로 갑니다 baseHandlers.이 메소드 createReactiveObject는 입력 파라미터의 세 번째 파라미터, 즉 mutableHandlers, Proxy의 공통 메소드를 포함합니다.

이미지.png

createGetterget메서드 를 호출한 후 실행되는 함수 입니다. 447행에서 자식이 여전히 객체인 경우 reactive딥 프록시를 수행하기 위해 재귀적으로 호출한다는 것을 발견했습니다. 이 시점에서 소스 코드가 손실된 응답, 즉 손실된 Reactivity는 Vue가 아니라 Proxy 개체 자체에 있습니다.

이미지.png

간단한 구현

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);
复制代码

값을 읽으려고 하면 get메서드 되고 값이 설정되면 set메서드가 호출됩니다. let { count } = proxy; count = 2구조화 및 재할당이 set메서드 호출을 트리거하지 않는 경우. 그런 다음 Destructuring이 참조 데이터 유형인 경우 이제 위의 코드를 변경해 보겠습니다.

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
复制代码

이 때, 위의 결론을 확인하는 get방법과 set방법 을 모두 호출합니다.

추천

출처juejin.im/post/7080127118486552584