[Vue.js] ref랑 reactive 어떤 거 써요?

39543 단어 Vue.jstech
Vue.js의 Composition API가 등장한 지 1년이 넘었으니 능숙하게 사용하는 사람이 있겠죠?
나는 업무 중에 Composition API를 사용했는데 이전의 Options API에 비해 UI와 논리의 분해가 더욱 쉬워졌다.구성 요소 외부에서 활성화된 데이터를 정의할 수 있으므로 한 구성 요소에 기록해야 하는 논리적 관심사로 나누어 다른 파일에 정의할 수 있습니다.
마치 React의 사용자 정의 낚싯바늘처럼 쓰여진 것 같다.
개인적으로, React가 클래스 구성 요소에서 함수 구성 요소 + 훅으로 이동하는 것처럼, Vue.js에서도 Composition API로 이동하는 절차가 있을 것이라고 생각합니다.
그렇다면 이러한 Composion API이지만 다시 활성화된 데이터를 정의할 때reactiveref 두 가지 방법이 있다.reactiveref 도대체 어떤 것을 사용하는 것이 좋을지 정부측에서 추천하는 방법도 없어서 어떤 것을 사용해야 할지 망설이고 있습니다.reactiveref 각각장점과단점을확인해보자.

reactive

reactive 방법은 대상을 매개 변수에 수신하고 활성화된 복사본을 되돌려줍니다.
<script setup lang="ts">
import { reactive, computed } from 'vue'

const state = reactive({
  count: 0
})

const increment = () => {
  state.count++
}
</script>

<template>
  <p>{{ state.count }}</p>
  <button @click="increment">+</button>
</template>

장점


Options API의 Data 정의와 유사

reactive 대상에 따라 정의된 것이지만 이 방법은 Options APIData의 정의 방법과 비슷해 기존의 방법에 익숙해진 사람에게는 ref에 비해 찾기 어려울 수 있다.
<script>
export default defineComponent({
  data() {
    return {
      count: 0
    }    
  },
  methods: {
    increment() {
      this.count++
    }
  }
})
</script>

통합 데이터 정의에 적합


예를 들어 사용자 데이터 중firstName,lastName처럼 관련 데이터 그룹을 정의할 때 사용ref은 단독 정의보다 개별적인 관련성을 이해하기 쉽다.
<script setup lang="ts">
import { reactive, ref } from 'vue';

const user = reactive({
  firstName: 'Jhon',
  lastName: 'Smith',
  age: 21,
});

const fullName = computed(() => `${user.firstName} ${user.lastName}`);

const firstName = ref('Jhon');
const lastName = ref('Smith');
const age = ref(21);

const fullName = computed(() => `${firstName.value} ${lastName.value}`);
</script>

결점


일반적인 대상과 구별하기 어렵다

reactive 방법의 반환값 형식은 원시 대상으로 유지됩니다.ref 제거되는 것과 다름)
한 마디로 하면 변수 유형 정보만 보면 그것이 일반 대상인지 활동 값인지 판단할 수 없다.
スクリーンショット 2021-12-30 19.38.33 ref에서 재활동 데이터를 정의하면 Ref<number>로 추론되기 때문에 유형 정보만 봐도 재활동 데이터임을 식별할 수 있다.
const count = ref(0) // Ref<number>

기간을 나누어 대입하다.

reactive 가장 큰 단점 중 하나는 분할대입을 하면 재활동성을 잃게 된다는 것이다.예를 들어, 디스플레이count를 다음과 같은 방법으로 분할하여 대입하려면 드로잉이 예상과 다르지 않습니다.
<script setup lang="ts">
import { reactive } from "vue";

const state = reactive({
  count: 0,
});

let { count } = state;

const increment = () => {
  count++;
};
</script>

<template>
  <p>{{ count }}</p>
  <button @click="increment">+</button>
</template>
count
분할 대입을 사용하려면 toRefsref로 변환하는 값으로 사용해야 한다.
<script setup lang="ts">
import { reactive, toRefs } from "vue";

const state = reactive({
  count: 0,
});

let { count } = toRefs(state);

const increment = () => {
  count.value++;
};
</script>

<template>
  <p>{{ count }}</p>
  <button @click="increment">+</button>
</template>
저는 개인적으로 이 분할대입이 불가능한 방법은 상당히 심각하다고 생각합니다.위에서 말한 바와 같이 reactive에서 선언한 데이터는 통상적인 대상과 다르지 않기 때문에 선언원 앞에서 대입을 분할할 수 있는지 확인하는 데 시간이 걸린다.코드reactive를 사용할 때도 일반 대상을 사용할 때 반드시 주의해야 한다.
reactive에서 선언한 데이터를 잘못 대입한 경우에도 별다른 경고 등 표시가 없어 값이 더 이상 활성화되지 않는 문제의 원인을 탐색할 때 다소 불편함을 느낄 수 있다.toRefs를 사용하는 방법도 toRefs 자체가 주요 API가 아니라 최종적으로ref로 바뀌면 원시적으로ref로 정의하면 되지 않겠는가?그런 마음도 든다.

Ref

ref 원시값string, number 등)을 매개 변수의 재활동 데이터로 정의한다.ref 방법의 반환값의 유형은 Ref<T>T가 파라미터 값에 맡긴 유형)의 대상이다.ref에 정의된 값은 value에 액세스해야 하는 속성입니다.<template>내 사용 시 생략.value할 수 있다.
베입니다.js에서 대상이 실현하는 주동성Proxy이기 때문에 원생의 형식으로 다시 활성화할 수 없는 경우가 있다.(Vue2에서Object.defineProperty
<script setup lang="ts">
import { ref } from "vue";

const count = ref(0)

const increment = () => {
  count.value++
}
</script>

<template>
  <p>{{ count }}</p>
  <button @click="increment">+</button>
</template>

장점


쉽게 판별할 수 있는 데이터는 활성화된 데이터입니다

reactive의 단점에서 설명한 바와 같이ref()의 반환값은Ref<T>이기 때문에 단순한 원시 데이터가 아니라 원시 데이터라고 판별하기 쉽다.
const count = ref(0) // Ref<number>

결점


항상.value 액세스 필요

ref에 정의된 값은 항상 .value에 접근해야 하기 때문에 남다른 방법이 필요하다.<template> 내부에서 생략할 수 있음.value도 혼란의 원인 중 하나)
이는 TypeScript 대신 JavaScript를 사용하는 경우에 두드러집니다.
예를 들어 boolean의 가격을 처리할 때 부주의로 추가하는 것을 잊어버리면 좀 곤란할까요?
import { ref } from "vue";

const isShow = ref(false);

if (isShow) {
  // 常に実行されてしまう!!
}

Compoosables 함수로 공개될 때 보통 Ref형


잡담은 그만두고, 나는 이전에 구성 요소 내의 사용을 고려해 왔는데, 지금 먼저 Compoosables 함수를 살펴보자.
Compoosables는 Composition API를 사용하여 상태의 완전한 논리를 재활용 가능한 함수로 정의합니다.예를 들어 .value 날짜 라이브러리는 날짜 형식 등 재사용 가능한 함수를 제공하는데 이것은 무상태 논리이다.상대적으로 상태 논리는 시간의 추이에 따라 변화하는 상태 관리를 포함한다.
예를 들어 Composition API를 사용하여 API 호출을 재사용할 수 있는 함수dayjs를 살펴보겠습니다.
import { Ref, ref, unref, watchEffect } from 'vue'

const useFetch = <T>(url: string | Ref<string>) => {
  const unrefUrl = unref(url)
  const data = ref<T | null>(null)
  const loading = ref(true)
  const error = ref<unknown | null>(null)

  const fetchData = async () => {
    loading.value = true
    error.value = null
    try {
      const res = await fetch(unrefUrl)
      data.value = await res.json()
    } catch (e) {
      error.value = e
    } finally {
      loading.value = false
    }
  }

  watchEffect(() => {
    fetchData()
  })

  return {
    data,
    loading
    error,
  }
}

export default useFetch
useFetchuseFetch를 매개 변수로 응답 데이터를 수신하고 불러올 수 있는지, 오류가 3개의 데이터를 불러올 수 있는지.반환된 데이터는 각자URL에 정의되어 있기 때문에 활성화 상태이며, 일정 시간이 지나면 API 호출이 완료되면 반환된 데이터의 상태가 변경됩니다.
또한 매개 변수의 URL을 재활성 데이터로 교부하면 매개 변수의 URL 변경(예: 쿼리 매개 변수 변경ref마다 API가 다시 호출됩니다.
또한Compoosables 함수watchEffect는 디렉터리에 설정composables+낙타 껍질의 함수 이름이 관례입니다.
이것은 구성 요소 내에서 다음과 같이 사용됩니다.
<script setup lang="ts">
import useFetch from "./useFetch";

interface User {
  firstName: string;
  lastName: string;
  age: number;
}
const { data, loading, error } = useFetch<User>("/api/users");
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">Error!</div>
  <div v-else>
    <p>{{ data?.firstName }} {{ data?.lastName }}</p>
  </div>
</template>
그러면 이런Compoosables 함수에 대해 공식적인 견해로 함수 내부의 상태를 유지하는 것을 추천합니다use. reactive는 어느 것을 사용하든지 반환값은 ref 형식으로 되돌아오지 않습니다reactive.
Returning a reactive object from a composable will cause such destructures to lose the reactivity connection to the state inside the composable.
If you prefer to use returned state from composables as object properties, you can wrap the returned object with reactive() so that the refs are unwrapped. For example:
https://staging.vuejs.org/guide/reusability/composables.html#return-values
const useFetch = <T>(url: string | Ref<string>) => {

  const state = reactive({
    data: null,
    loading: true,
    error: null,
  })

  // bad practice...
  return state
  // better
  return toRefs(state)

  // or...
  const data = ref<T | null>(null)
  const loading = ref(true)
  const error = ref<unknown | null>(null)

  return {
    data,
    loading,
    error,
  }
}
구성 요소 내에서Compoosables 함수를 사용할 때 재활성을 잃는 것을 방지하기 위해서입니다.위에서 말한 바와 같이Ref 분할 대입을 하면 재활동성을 잃게 된다.
const { data, loading, error } = useFetch('/api/users')

사견


그럼 reactivereactive 어떤 것을 사용하는 것이 좋을지 다시 이야기해 봅시다.제 개인적인 의견으로는 구성 요소 내에서 자주 사용하는 것이 좋습니다ref.
이유는 ref에서 분할 대입을 한 후 주동성을 잃었기 때문이다.최종적으로reactive에서 toRefs로 전환해야 한다면 원시적으로Ref로 데이터를 이해하기 쉬운 접근 방법을 정의하는 것도 통일적이다.ref도 마찬가지로 computed접근 데이터).value에는 항상 ref를 넣어야 하기 때문에 이해하기 어렵지만 .value를 사용하면 큰 문제가 되지 않을 거라고 생각합니다.(또 VScode의 확장Volar을 사용하면 TypeScript를 보충할 수 있다.
ref-value1
예외적으로Compoosables 함수에서 상태를 정의할 때 봉인되어 있기 때문에 반드시 .value 반환 조건toRefs()을 사용해야 한다.

좋은 웹페이지 즐겨찾기