options-based API의 경우 prop, data, computed, hook 등의 옵션으로 로직이 분리되어있어 논리적 관점 단위로 개발을 하기 애매하게 만든다. 예를 들면 사용자 조회라는 로직이 있을경우, 관련 로직이 data와 computed, 특정 method 에 흩어질 수 있다. 이것을 극복하기위해 Composition API가 만들어졌다.
setup 이라는 옵션이 생겼고, 이 안에서 Composition API를 사용할 수 있다.
export default {
props: {
user: { type: String }
},
data(){
return {
test: '',
}
},
setup(props) {
console.log(props); // { user: '' }
return {}; // 여기서 반환된 내용은 컴포넌트의 "rest"에서 사용할 수 있습니다
}
// 컴포넌트의 "rest" 부분
}
<script setup>
사용하기<script setup>
// variable
const msg = 'Hello!';
// functions
function log() {
console.log(msg);
}
</script>
<template>
<div @click="log">{{ msg }}</div>
</template>
<script setup>
은 컴포넌트의 인스턴스가 생성될때마다(created) 호출된다. 따라서 setup()
내부의 this
는 현재 활성화된 인스턴스에 대한 참조가 아니다. created 관련 훅도 필요하지 않다.
여기서 선언된 탑 레벨 변수 및 하수는 모두 템플릿에서 바로 사용할 수 있다. 우리가 종종 사용하는 유틸함수들도 import 후 바로 템플릿에서 사용할 수 있다.
<script setup>
import { u_capitalize } from './utils';
</script>
<template>
<div>{{ u_capitalize('hello') }}</div>
</template>
처음부터 options-basedAPI를 사용하지 않고 <script setup>
을 사용하는것을 추천한다.
Vue 2.x의 Options-based API의 data()
함수에서 세팅된 변수는 모두 자동으로 반응성을 얻게 되는데, Composition API 에서는 반응성 변수를 만들기 위해서는 **Reactivity API를 직접 활용해야 한다**.
Reactivity API는 2.x에서의 Vue.observable() API 에서 온 것인데 RxJS의 observables 과 혼동을 피하기 위해 이름을 바꿨다. 이것은 Vue 의 핵심 기능이다. 뷰는 종속성 추적을 통해 반응형 값들의 상태가 변경될때 화면을 자동으로 업데이트 한다.
ref()
Reactivity API 중 하나인 ref
함수는 원시값에 대해 반응성을 부여할때 사용하면 된다.
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
ref
함수는 불변성의 원시값을 내부 값으로 취한다음 변경가능하고 반응성이 있는 객체를 리턴한다.(ref wrapping) 이 객체는 내부 값을 가리키는 .value
라는 속성 가진다. 템플릿에서 사용될때는 값에 접근할때 자동으로 .value
속성으로 반환(Unwrapping)된다. 스크립트 안에서 값을 변경하기 위해서는 직접 .value
속성을 사용해야 한다.
<script setup>
import { ref } from 'vue';
const count = ref(0);
const handleClickAdd = () => {
count.value++;
}
</script>
<template>
<button @click="handleClickAdd">{{ count }}</button>
</template>
객체값에 반응성을 부여하고 싶다면 reactive 함수를 사용하면 된다. 이때 속성의 값을 변경하려고 하면 자동으로 Unwrapping 이 동작한다.
const obj = reactive({ count: 0 });
obj.count++; // 자동으로 unwrapping 된다.
reactive로 감싼 객체가 Array나 Map과 같이 표준 내장 컬렉션 타입인 경우 자동 Unwrapping이 동작하지 않는다.
const books = reactive([ref('Vue 3 Guide')])
// 여기에는 .value 가 필요합니다.
console.log(books[0].value)
computed()
import { ref, computed } from 'vue'
const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)
counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2
watch 사용하기
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log('새로운 counter 값: ' + counter.value)
})
props, emit
<script setup>
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
// setup code
</script>
상태관리
참고자료