
컴포넌트 내부에서 함수를 만들 때 보통 methods에 작성하는데,
실제로는 계산된 값으로 작성할 수도 있습니다.
computed는 컴포넌트 로드 시 한 번 실행되고, 그 결과를 캐싱해두므로
반복 호출해도 내부 코드가 다시 실행되지 않습니다.
Vue2 예시 (Vuex 이전 방식):
computed: { now2(){ return new Date() } }, methods: { now(){ return new Date() } }
- methods: 호출할 때마다 새로 실행
- computed: 최초 계산 후 결과를 저장해 재사용
<script setup>에서 computed 사용 예시<script setup>
import { computed } from 'vue'
const now = computed(() => new Date())
</script>
<template>
<!-- 함수 호출할 때는 소괄호 없이 computed 변수명만 사용 -->
<div>{{ now }}</div>
</template>
포인트: computed는 함수보다는 계산 결과를 저장하는 "계산 캐시" 역할
<template>
<div>
<input v-model="num1" type="number" placeholder="숫자 1" />
<input v-model="num2" type="number" placeholder="숫자 2" />
<p>합계: {{ sum }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
// 반응형 변수 선언
const num1 = ref(0)
const num2 = ref(0)
// computed를 사용해 두 숫자의 합계를 계산
const sum = computed(() => {
return Number(num1.value) + Number(num2.value)
})
</script>
이 코드에서는:
computed를 사용해 num1과 num2의 합계를 계산하는 반응형 값을 정의합니다.v-model을 사용하여 입력 값을 반응형 변수와 바인딩하고, 계산된 합계 sum을 출력합니다.참고: Vue 공식 문서 및 다양한 Vue3 튜토리얼에서 이와 유사한 예시를 확인할 수 있습니다.
Vue 파일 내에서 상태를 꺼내쓸 때
// Vuex 사용 시 (Vue2 문법)
this.$store.state.name
이런 식으로 긴 경로를 사용하게 됩니다.
자주 사용하는 state라면 computed에 넣어두면 조금은 편해집니다.
computed: {
name(){
return this.$store.state.name
}
}
이렇게 하면 템플릿에서는 {{ name }}으로 바로 접근할 수 있습니다.
또, 여러 state를 한 번에 가져오고 싶다면 Vuex의 mapState 함수를 사용할 수 있습니다.
import { mapState } from 'vuex'
computed: {
...mapState(['state이름1', 'state이름2']),
// 또는 이름 변경 가능
...mapState({ 작명: 'state이름1' })
}
또한, mutations도 mapMutations를 사용하면
import { mapState, mapMutations } from 'vuex'
computed: {
...mapState(['state이름1', 'state이름2'])
},
methods: {
...mapMutations(['좋아요', 'setMore'])
}
이렇게 하면 $store.commit('좋아요') 대신 좋아요()로 호출할 수 있습니다.
Pinia에서는 Vuex의 mapState, mapMutations 등의 별도 헬퍼 함수 없이
스토어 인스턴스를 직접 가져와 사용하면 되며,
storeToRefs를 이용해 상태들을 개별 ref로 변환할 수 있습니다.
// stores/myStore.js
import { defineStore } from 'pinia'
export const useMyStore = defineStore('myStore', {
state: () => ({
name: 'Pinia 예제',
state이름1: '값1',
state이름2: '값2'
}),
actions: {
좋아요() {
// 기존 commit 대신 직접 액션 실행
console.log('좋아요 액션 실행')
},
setMore(payload) {
// 추가 액션 처리
console.log('setMore 호출', payload)
}
}
})
<script setup>)<script setup>
import { storeToRefs } from 'pinia'
import { useMyStore } from '@/stores/myStore'
// Pinia 스토어 인스턴스 가져오기
const myStore = useMyStore()
// storeToRefs로 state를 ref로 변환하면, 템플릿에서 바로 사용 가능
const { name, state이름1, state이름2 } = storeToRefs(myStore)
// computed를 따로 작성할 필요 없이, state는 반응형(ref)로 관리됨
// 액션은 함수처럼 직접 호출 가능: myStore.좋아요()
</script>
<template>
<div>
<h1>{{ name }}</h1>
<p>{{ state이름1 }} / {{ state이름2 }}</p>
<button @click="myStore.좋아요()">좋아요</button>
<!-- setMore 액션 호출 예시 -->
<button @click="myStore.setMore('추가 데이터')">setMore 호출</button>
</div>
</template>
포인트:
- Vuex에서는
$store.state.name처럼 긴 경로를 사용했지만,- Pinia에서는
storeToRefs를 사용하여 간편하게name등의 state에 바로 접근할 수 있습니다.- 또한, action(이전의 mutations 포함)은
myStore.좋아요()처럼 바로 호출할 수 있어 코드가 훨씬 깔끔해집니다.
<script setup>에서는 import { computed } from 'vue'로 사용합니다.this.$store.state와 mapState, mapMutations 등을 사용해 상태와 액션을 관리했지만, Pinia에서는 useMyStore()로 스토어 인스턴스를 가져오고, storeToRefs를 사용해 state를 개별 ref로 만들어 템플릿에서 간편하게 사용합니다.