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
구조분해할당
을 사용하면 반응성이 제거
된다.context
attrs, 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>