원래 프로젝트가 커지면 데이터가 어디 있는지 찾기 어렵고 관리가 복잡해지는 Vue 의 단점을 보완하기 위해 Vue3 부터 등장했습니다.
<template>
<button @click="increment">
Count is: {{ count }}, double is: {{ double }}
</button>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
computed: {
double() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
}
}
</script>
위에서 볼 수 있듯이, count
의 값을 변화시키는 로직이 computed
와 methods
에 흩어져있습니다. 지금 예제는 간단해지지만 각각의 data 에 대해 로직이 100개가 존재한다면 ? 내가 원하는 데이터가 어디에서 처리되고 있는지 확인이 어렵겠죠.
<template>
<div>
<button @click="increment">
Count is: {{ count }}, double is: {{ double }}
</button>
<input type="text" v-model="inputValue"/>
reversed : {{ reversedInputValue }}
</div>
</template>
<script>
import {ref, computed, onMounted, onUnmounted} from 'vue'
export default {
setup() {
return {
...useCount(),
...useHandleInput(),
...useMousePosition()
}
}
}
function useCount() {
const count = ref(0);
const double = computed(() => count.value * 2);
const increment = () => count.value++;
return {count, double, increment};
}
function useHandleInput() {
const inputValue = ref('');
const reversedInputValue = computed(() => inputValue.value.split('').reverse().join(''));
return {inputValue, reversedInputValue};
}
function useMousePosition() {
const x = ref(0);
const y = ref(0);
const mousePositionUpdate = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', mousePositionUpdate)
})
onUnmounted(() => {
window.removeEventListener('mousemove', mousePositionUpdate)
})
return {x, y}
}
</script>
composition api 를 사용해 input
, count
, mousePosition
각 값들에 대한 관심사를 각각 useCount
, useHandleInput
, useMousePosition
로 묶어서 처리하게 되어 count 관련 변경점이나 확인사항이 필요할 시 useCount
만 확인하면 되어 더욱 간결하고 직관적인 처리가 가능하도록 되었습니다. 이러한 관심사는 하단 이미지 처럼 각 관심사별로 큰 덩어리로 분리될 수 있습니다.
<template>
<div>{{ count }}</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count,
}
}
}
</script>
setup 함수는 beforeCreate 생명주기 전에 호출되는 composition aPi 사용을 위한 진입점 역할을 담당합니다. setup 함수는 lifeCycle 에서 beforeCreate와 create의 역활도 대체 합니다. 해당 함수내에서 기존의 data, computed, method, lifeCycle 에 대한 설정이 한번에 가능합니다.
setup 에서 data 선언 시 2가지로 선언이 가능합니다.
이때 ref로 선언한 값은 반드시 .value
를 통해 접근해야 실제 값을 받아올 수 있습니다. 그러나 위의 예제처럼 바로 template에서 사용할 경우는 생략이 가능합니다.
<template>
<div>{{ count }} {{ object.foo }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const count = ref(0)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 1
return {
count
}
}
}
</script>
setup 함수 내에서 computed 를 사용하고 싶다면 computed(fn)
를 감싸서 값을 선언해줍니다.
import { onMounted, onUpdated, onUnmounted } from '@vue/composition-api'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
setup 함수에서는 원래 생명주기 함수 앞에 on
을 추가하여 다음과 같이 사용하실 수 있습니다.
제공하는 생명주기는 다음과 같습니다.
기존에 컴포넌트당 단 하나의 생명 주기 훅만 사용이 가능했지만, 관심사에 따라 분류가 되는 composition api 에서는 여러개로 나누어 사용이 가능합니다. 아래처럼 말이죠.