Composition API 설치
- install
npm install @nuxtjs/composition-api --save
- plugin 추가
https://bitbucket.org/backpackr/web.idus.com/src/f71db99f7dbd/plugins/composition-api.plugin.ts - nuxt.config.ts > buildModules 추가
buildModules: [
...
'@nuxtjs/composition-api/module'
],
Composition API 사용 하기
- Composition API import
import {reactive, ref} from "@nuxtjs/composition-api";
- setup()에 전달된 인자에 대한 타입을 추론하려면, defineComponent 를 사용해야한다. #
<script lang="ts">
export default defineComponent({
name: 'HomePage',
components: {
Logo,
},
setup() {
const count: number = ref(0)
return { count }
}
})
</script>
Ref
- setup 안에서 ref 를 출력할 땐 .value 를 붙여줘야한다.
let count = ref(0)
console.log(count.value)
- 위 처럼 타입을 정의하지 않아도 알아서 타입을 체크하지만, ref 에 타입을 정의하고 싶다면 다음과 같이 두가지 방법이 있다
첫번째 방법은 여러 타입을 정의할 때 사용하고, 두번째 방법은 기존에 지정 했던 타입을 재정의 할 때 사용하길 권장한다. #
const count: Ref<number | string> = ref('0') // 또는
const count = ref<number | string>(0)
Reactive
- ref 와 달리 reactive 는 중첩된 타입을 가지 않는것을 권장한다. #
그래서 그런지 위와 같이 여러 타입 정의할 수 있도록 도와주는 interface 가 존재하지 않는다. 😒 - 출력은 ref 와 다르게 .value 없이 사용한다.
const header = reactive<IHeader>({ title: 'hello idus', useLogo: false }) // 또는
const header: IHeader = reactive({ title: 'hello idus', useLogo: false })
console.log(header.title)
Computed
- get 만 할 경우
const handleClickInclude = () => count.value++
const handleClickExclude = () => count.value--
- get, set 모두 사용할 경우
const computedText = computed({
get: (): string => text.value,
set: (newText): string => text.value = newText
})
- 타입을 지정하고 싶으면 다음과 같이 사용하면 된다.
const computedText = computed<string>({
get: (): string => text.value,
set: (newText): number => text.value = newText
})
// 여러 타입 정의 시 ComputedRef 사용한다.
const style: ComputedRef<IBgStyle | undefined> = computed(() => {
if (props.backgroundColor) {
return {
backgroundColor: props.backgroundColor,
}
}
})
- 타입 지정할 때 볼 수 있듯이 computed 를 setup 안에서 사용할 땐 ref 처럼 .value 를 붙여줘야한다.
console.log(computedText.value)
Function
- 모두가 아는 그것. 설명을 생략하겠다.
- 아! 😮 ref, reactive, computed, function 등 모두 template 에서 사용하려면 return 을 해줘야한다.
setup() {
const count = ref(0)
const handleClickInclude = () => count.value++
const handleClickExclude = () => count.value--
return {
count,
handleClickInclude,
handleClickExclude
}
}
- 위 코드는 간단하지만 코드가 길어지면 Composition API 사용하는데 의미가 없다. #
Watch
- 한개의 소스만 Watch 할 경우, ref 일 경우와 아닐 경우 사용 방법이 다르다. #
// ref watch 할 경우
const count = ref(0)
watch(count, (count, prevCount) => {
...
})
// reactive, props (getter) 등을 watch 할 경우
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
...
}
)
- 여러 소스를 Watch 할 경우는 다음과 같이 사용한다.
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
...
})
Props
- 자식 Component 에서 Props 을 선언할 땐 다음과 같이 defineComponent 안에 setup 보다 위에 선언한다.
- 기존과 다른점이라면 Array 나 Object 에 as PropType<YourInterface> 를 사용해 타입을 지정할 수 있다는 것이다.
export default defineComponent({
name: 'ProductList',
props: {
products: {
type: Array as PropType<IProduct[]>, // Array 에 타입 정의
required: true
},
order: {
type: String,
required: true
}
},
setup() {
...
}
})
- setup 은 2가지의 인자를 전달하는데 props 와 context 이다. 따라서 자식 Component 에서 Props 로 받은 데이터를 setup 안에서 사용하고 싶다면 다음과 같이 사용하면 된다.
export default defineComponent({
name: 'ProductList',
...
setup(props) {
return {
...useOrderedProduct(props),
...useOrderClasses(props)
}
}
})
- Props 의 타입은 defineComponent 가 알아서 찾아주니 선언할 필요는 없다고 한다 #
Emit
- setup 전달인자 중 context 안에 있는 emit 을 활용한다.
setup(props: ICommonButtonProps, { emit }: SetupContext) {
...
const handleClickButton = () => {
emit('click')
}
return {
classes,
style,
handleClickButton
}
}
Lifecycle Hooks
- 이전 스터디때 설명 드렸던 바와 같이 beaforCreate, created hook을 setup 훅으로 대체하여 사용되고, 그 외 기존과 다르게 다음과 같이 Lifecycle이 달라지고 사용할 땐 앞에 on을 붙여서 사용 한다.
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
Template reference
- Composition API를 사용하면, reactive refs API와 template 의 refs의 개념이 통합됩니다. template 내 ref 를 사용하고 싶다면 기존과 같이 ref를 선언하고 setup에서 반환하면 된다.
<template>
<div class="ProductList" ref="root">
...
</div>
</template>
<script>
import {defineComponent, onMounted, ref} from "@nuxtjs/composition-api";
export default {
setup() {
const root = ref(null)
onMounted(() => {
console.log(root.value) // <div class="ProductList">...
})
return {
root
}
}
</script>