템플릿 내 표현식은 매우 편리하지만 간단한 작업을 위한 것임.
템플릿에 너무 많은 논리를 넣으면 비대해져 유지 관리가 어려워질 수 있음.
예를 들어 객체 내 벼열이 있는 경우.
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery',
]
})
그리고 author
가 이미 책을 가지고 있는지에 따라 다른 메시지를 표시하고 싶으면
<p> 책을 가지고 있음. </p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
이 시점에서 템플릿이 약간 복잡해짐.
우리가 여기서 인지해야 할 요점은 템플릿의 반응형 결과가 author.books
에 의해 계산된다는 점보다, 템플릿 내에서 이 코드를 두번 이상 반복하고 싶지 않다는 것임.
따라서 반응형 데이터를 포함하는 복잡한 논리의 경우, computed를 사용하는 것이 좋음.
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 계산된 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>책을 가지고 있다:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
여기서 computed publishedBooksMessage
를 선언함. computed()
함수에는 getter로 사용될 함수가 전달돼야 하며, 반환되는 값은 computed ref임. 일반 ref와 유사하게 계산된 결과를 publishedBookMessage.value
로 접근할 수 있음.
계산된 ref는 템플릿에서 자동으로 언래핑되므로, 템플릿 표현식에서 .value
없이 참조할 수 있음.
computed는 의존된 반응형을 자동으로 추적함.
Vue는 publishedBooksMessage
의 값이 author.books
에 의존한다는 것을 알고, author.books
가 변경되면 publishedBooksMessage
를 바인딩해 읜존하는 모든 것을 업데이트함.
표현식에서 메서드를 호출하여 동일한 경과를 얻을 수 있음.
<p>{{ calculateBooksMessage() }}</p>
// 컴포넌트 내에서
function calculateBooksMessage() {
return author.books.length > 0 ? 'Yes' : 'No'
}
계산된 속성 대신 메서드로 동일한 기능을 정의할 수 있음.
결과적으로 두 가지 접근 방식은 실제로 완전히 동일함. 그러나 차이점은 계산된 속성은 의존된 반응형을 기반으로 캐시된다는 점.
계산된 속성은 의존된 반응형 중 일부가 변경된 경우에만 재평가됨.
즉, author.books
가 변경되지 않은 한 여러 곳에서 publishedBooksMessage
에 접근할 경우, getter함수를 다시 실행하지 않고 이전에 계산된 결과를 즉시 반환함.
이와 반대로 메서드 호출은 리렌더링이 발생할 때마다 항상 함수를 실행함.
캐싱이 필요한 이유는 캐싱이 없다면 list
의 getter를 불필요하게 많이 실행할 것임.
캐싱을 원하지 않는 경우에만 메서드 호출을 사용할 것.
computed는 기본적으로 getter 전용임.
계산된 속성에 새 값을 할당하려고 하면 런타임 에러가 발생함.
드물게 '수정 가능한' 계산된 속성이 필요한 경우, getter와 setter를 모두 제공하여 속성을 만들 수 있음
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 참고: 분해 할당 문법 사용
[firstName.value, lastName.value] = newValue.slit(' ')
}
})
</script>
fullName.value = 'Jogn Doe'
를 실행하면 setter가 호출되고, 그에 따라 firstName
과 lastName
이 업데이트됨.