일반적인 script 실행과 대비해서 computed의 큰 차이점은 값을 caching 한다는 점이다. template에서 script(즉 함수)를 직접 실행하는 경우는 당연히 사용되는 회수만큼 함수가 동작하지만 computed는 한번 동작한 후 그 값을 caching 해서 사용한다. 따라서 종속 대상이 변경되지 않으면 다시 계산하지 않는다.
다음의 코드는 일반 함수인 sumM과 computed인 sumC가 선언되어 있다. 이 둘은 모두 dan이라는 변수에 종속되어있다.
<script>
const { createApp, ref, computed } = Vue;
createApp({
setup() {
const dan = ref(1);
const sumM = () => {
// 단에 대한 합 구하기
let sum = 0;
for (let i = 1; i < 10; i++) {
sum += dan.value * i;
}
console.log(`sum: ${sum}`);
return sum;
};
const sumC = computed(sumM);
return { dan, sumM, sumC };
},
}).mount("#app");
</script>
template에서는 sumM과 sumC를 각각 2번씩 사용하고 있다. sumM은 단순 함수 이기 때문에 ()를 붙여서 실행해주고 sumC는 마치 data 처럼 사용되므로 ()가 없다는 점도 주목하자.
<div id="app">
<input type="text" v-model.number="dan"/>의 합은?<br />
<ul>
<li>method 두 번 호출: {{sumM()}}, {{sumM()}}</li>
<li>computed 두 번 사용: {{sumC}}, {{sumC}}</li>
</ul>
</div>
위 코드를 실행시켜 보면 sumM은 2번, sumC는 한번만 동작함을 알 수 있다. 각각의 종속값인 dan을 변경시켜도 결과는 동일하다.
수정 가능한 계산된 속성
computed는 "이미 계산된 속성"이기 때문에 대부분 read only 형태로 사용하며 새로운 값을 할당하려고 하면 runtime error가 발생한다. computed는 readonly가 국룰이다.
const user = ref({
first: "gil dong",
last: "hong"
});
const computedName1 = computed(() => {
return `${user.value.first}(${user.value.last})`;
});
console.log(computedName1.value)
// runtime 오류 - 실제로는 반영되지 못한다.
computedName1.value = "some"
하지만 꼭 수정해야 한다면 computed에 get과 set 함수를 가진 객체를 전달하고 set 함수에서 값을 변경할 수는 있다.
// 쓰기 가능
function computed<T>(
options: {
get: (oldValue: T | undefined) => T
set: (value: T) => void
}
): Ref<T>
const user = ref({
first: "gil dong",
last: "hong"
});
const computedName2 = computed({
get() {
return `${user.value.first}(${user.value.last})`;
},
set(newVal) {
[user.first, user.last] = newVal;
}
});
// setter 호출 - 전체적인 값의 변화가 발생한다.
computedName2.value = ["몽룡", "임"]