[Vue.js] ref랑 reactive 어떤 거 써요?
나는 업무 중에 Composition API를 사용했는데 이전의 Options API에 비해 UI와 논리의 분해가 더욱 쉬워졌다.구성 요소 외부에서 활성화된 데이터를 정의할 수 있으므로 한 구성 요소에 기록해야 하는 논리적 관심사로 나누어 다른 파일에 정의할 수 있습니다.
마치 React의 사용자 정의 낚싯바늘처럼 쓰여진 것 같다.
개인적으로, React가 클래스 구성 요소에서 함수 구성 요소 + 훅으로 이동하는 것처럼, Vue.js에서도 Composition API로 이동하는 절차가 있을 것이라고 생각합니다.
그렇다면 이러한 Composion API이지만 다시 활성화된 데이터를 정의할 때
reactive
와 ref
두 가지 방법이 있다.reactive
과ref
도대체 어떤 것을 사용하는 것이 좋을지 정부측에서 추천하는 방법도 없어서 어떤 것을 사용해야 할지 망설이고 있습니다.reactive
와ref
각각장점과단점을확인해보자.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
제거되는 것과 다름)한 마디로 하면 변수 유형 정보만 보면 그것이 일반 대상인지 활동 값인지 판단할 수 없다.
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>
분할 대입을 사용하려면
toRefs
를 ref
로 변환하는 값으로 사용해야 한다.<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
useFetch
는 useFetch
를 매개 변수로 응답 데이터를 수신하고 불러올 수 있는지, 오류가 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:
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')
사견
그럼
reactive
과reactive
어떤 것을 사용하는 것이 좋을지 다시 이야기해 봅시다.제 개인적인 의견으로는 구성 요소 내에서 자주 사용하는 것이 좋습니다ref
.이유는
ref
에서 분할 대입을 한 후 주동성을 잃었기 때문이다.최종적으로reactive
에서 toRefs
로 전환해야 한다면 원시적으로Ref
로 데이터를 이해하기 쉬운 접근 방법을 정의하는 것도 통일적이다.ref
도 마찬가지로 computed
접근 데이터).value
에는 항상 ref
를 넣어야 하기 때문에 이해하기 어렵지만 .value
를 사용하면 큰 문제가 되지 않을 거라고 생각합니다.(또 VScode의 확장Volar을 사용하면 TypeScript
를 보충할 수 있다.예외적으로Compoosables 함수에서 상태를 정의할 때 봉인되어 있기 때문에 반드시
.value
반환 조건toRefs()
을 사용해야 한다.
Reference
이 문제에 관하여([Vue.js] ref랑 reactive 어떤 거 써요?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/azukiazusa/articles/ref-vs-article텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)