composition API는 분산되어 있는 로직을, 관련 있는 로직들끼리 그룹핑하기 위해 만들어졌다.
기존 문법은 아래와 같이 여러 로직들이 섞인채로 작성되도록 설계되어 있다.
<!-- 기존 문법 -->
<template>
<h2 @click="increase">
{{ count }}
</h2>
<h2 @click="changeMessage">
{{ message }}
</h2>
</template>
<script>
export default {
data() {
return {
count: 0, // count 관련 로직
message: 'Hello jude' // message 관련 로직
}
},
methods: {
increase() { // count 관련 로직
this.count += 1
},
changeMessage() { // message 관련 로직
this.message = 'text change'
}
}
}
</script>
하지만 composition api 문법을 사용하면 아래와 같이 관련 있는 로직별로 그룹핑하는 것이 가능해진다.
<template>
<h2 @click="increase">
{{ count }}
</h2>
<h2 @click="changeMessage">
{{ message }}
</h2>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0) // count 관련 로직
const increase = () => count.value += 1 // count 관련 로직
const message = ref('Hello jude') // message 관련 로직
const changeMessage = () => message.value = 'text change' // message 관련 로직
return {
count, // count 관련 로직
increase, // count 관련 로직
message, // message 관련 로직
changeMessage // message 관련 로직
}
}
}
</script>
setup()함수 안의 로직에 사용된 변수들은객체로 만들어서return시키면template에서 사용할 수 있다.
setup() 함수 안에 사용되는 원시값(Number, String, Boolean 등..)들은 기본적으로 반응성을 가지고 있지 않다.
때문에 반응성을 주입해주기 위해 vue 패키지로부터 ref 메서드를 가져와서 원시값들을 아래와같이 래핑해서 사용한다.
const count = ref(0)
ref 메서드는 원시값을 value 키로 감싼 객체를 반환 시킨다.
때문에 원시값들을 사용할 땐 count.value와 같이 체이닝 하여 사용해야 한다.
console.log( count ) // { value: 0 }
console.log( count.value ) // 0
반응성을 주입한 변수를 setup() 함수 안에서 사용할 땐 value 프로퍼티에 접근하여 사용해야하지만, return키워드로 반환할 때는 자동으로 래핑 해제되기 때문에 value 프로퍼티 없이 그대로 반환하여 사용할 수 있다.
<template>
<div>{{ count }}</div><!-- 0 -->
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
console.log( count.value ) // 0
return {
count
}
}
}
</script>
computed()는 ref처럼 vue 패키지에서 import하여 사용한다.computed() 함수 호출을 할 때 인자에 콜백함수를 넣어 계산된 로직을 작성한다.<template>
<div>{{ count }}</div><!-- 1 -->
<div>{{ doubleCount }}</div><!-- 2 -->
</template>
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const count = ref(1)
const doubleCount = computed(() => count.value * 2)
return {
count,
doubleCount
}
}
}
</script>
watch() 역시 vue 패키지에서 import하여 사용한다.watch() 함수는 별도로 return 시킬 필요가 없다.첫번째 인자는 바라보고 있을 데이터명을 작성한다.두번째 인자는 콜백함수이며 데이터가 변경됐을 때 호출된다.콜백함수가 호출될 때 첫번째 매개변수로 변경된 값이 들어온다.<template>
<div>{{ count }}</div><!-- 1 -->
<div>{{ doubleCount }}</div><!-- 2 -->
<button @click="increase">증가 버튼</button>
</template>
<script>
import { ref, computed, watch } from 'vue'
export default {
setup() {
const count = ref(1)
const doubleCount = computed(() => count.value * 2)
function increase() {
count.value += 1
}
watch(doubleCount, newVal => {
console.log( newVal )
})
return {
count,
doubleCount,
increase
}
}
}
</script>
Child 컴포넌트로 class와 style 속성을 내려보내고 있다.Child 컴포넌트로 color라는 props를 내려보내고 있다.Child 컴포넌트로부터 childEvt 이벤트가 발생하면, log 함수를 호출한다.<!-- App.vue -->
<template>
<Child
class="jude"
style="color:red"
color="#ff0000"
@childEvt="log">
Apple
</Child>
</template>
<script>
import Child from './components/Child'
export default {
components: {
Child
},
methods: {
log() {
console.log( 'Hello jude!' )
}
}
}
</script>
App.vue에서 받은 속성들을 v-bind="$attrs"로 모두 상속받고 있다.클릭하면 hello 함수가 호출된다.hello 함수가 호출되면, emit을 통해 App.vue(부모 컴포넌트)에 childEvt 이벤트를 호출 시킨다.composition api 문법에선 created 라이프 사이클이 없다. setup() 함수에 작성하면 된다.composition api의 라이프사이클 훅은 vue 패키지로부터 import해서 사용하며, 이름이 기본 문법과 다르게 접두사로 on이 들어가고 카멜케이스로 작성한다.(ex. onMounted)onMounted() 라이프사이클 훅은 함수처럼 호출하고, 인자로 익명의 콜백함수를 선언하여 코드를 작성한다.props구조분해할당을 사용하면 반응성이 제거된다.contextattrs, slots, emit객체를 가져와 활용할 수 있다.<!-- Child.vue -->
<template>
<div
v-bind="$attrs"
class="btn"
@click="hello">
<slot></slot>
</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
inheritAttrs: false,
props: {
color: {
type: String,
default: 'gray'
}
},
emits: ['childEvt'],
setup(props, context) {
function hello() {
context.emit('childEvt')
}
onMounted(() => {
console.log(props.color);
console.log(context.attrs);
})
return {
hello
}
}
}
</script>
<!-- 렌더된 코드 -->
<div class="jude btn" style="color: red;"> Apple </div>