Props 타입 설정
기본 Props 정의
<template>
<div>{{ props.message }}</div>
<div>{{ props.numbers }}</div>
</template>
<script setup lang="ts">
interface Props {
message?: string,
numbers?: number[]
}
const props = defineProps<Props>();
</script>
키워드 '?'를 붙이면 Optional 한 Prop이 되고 붙이지 않으면 Required 한 Prop이 된다.
Props Default 값 설정
기본 타입 Default 값 설정
<template>
<div>{{ props.message }}</div>
</template>
<script setup lang="ts">
interface Props {
message?: string,
}
const props = withDefaults(defineProps<Props>(), {
message: 'this is default message'
});
</script>
Props의 Default 값을 설정하려면 Vue에서 제공해 주는 withDefaults라는 컴파일러 매크로를 사용해야 한다. 첫 번째 인수는 defineProps<Props>() 매크로를 넣어주고 두 번째 인수는 객체를 정의하여 각 Prop별로 default 값을 설정해 주면 된다.
배열(Array) Default 값 설정
<template>
<div>{{ props.numbers }}</div>
</template>
<script setup lang="ts">
interface Props {
numbers?: number[]
}
const props: Props = withDefaults(defineProps<Props>(), {
numbers: () => [1, 2, 3, 4, 5]
})
</script>
배열은 화살표 함수를 사용하여 default 값을 설정해 줄 수 있다고 공식문서에 나와있다.
객체 Default 값 설정
<template>
<div>{{ props.book.title }}</div>
<div>{{ props.book.author }}</div>
</template>
<script setup lang="ts">
interface Book {
title: string,
author?: string
}
interface Props {
book?: Book
}
const props: Props = withDefaults(defineProps<Props>(), {
book: (): Book => ({
title: 'The Black Cat',
author: 'Edgar Allan Poe' // optional
})
})
</script>
객체도 배열처럼 default 값을 설정하려면 화살표 함수를 사용하면 되는데 추가로 반환 타입을 명시해 줘야 하는 것 같다.
Emits 타입 설정
부모에게 넘길 값이 있을 때 - 함수 미사용
<template>
<button @click="handleSendClick">Send message</button>
</template>
<script setup lang="ts">
const emits = defineEmits<{
(e: 'update:message', message: string): void
}>();
const handleSendClick = (): void => {
emits('update:message', 'send message');
}
</script>
Child.vue
<template>
<Child @update:message="message => receivedMessage = message" />
<div>{{ receivedMessage || '받은 메시지가 없음' }}</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue';
const receivedMessage = ref('');
</script>
Parent.vue
부모에게 넘길 값이 있을 때 - 함수 사용
<template>
<button @click="handleSendClick">Send message</button>
</template>
<script setup lang="ts">
const emits = defineEmits<{
(e: 'update:message', message: string): void
}>();
const handleSendClick = (): void => {
emits('update:message', 'send message');
}
</script>
Child.vue
<template>
<Child @update:message="receiveMessage" />
<div>{{ receivedMessage || '받은 메시지가 없음' }}</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue';
const receivedMessage = ref('');
const receiveMessage = (message: string): void => {
receivedMessage.value = message;
}
</script>
Parent.vue
함수를 사용하지 않았을 때와 동일한 기능을 수행한다. 넘겨받은 값이 함수의 인수에 자동으로 주입(?)된다. 위 코드에서는 Child가 전송한 message가 receiveMessage() 함수의 첫 번째 인수인 message에 주입된다.
부모에게 넘길 값이 없을 때
<template>
<button @click="handleSendClick">Send message</button>
</template>
<script setup lang="ts">
const emits = defineEmits<{
(e: 'update:message'): void
}>();
const handleSendClick = (): void => {
emits('update:message');
}
</script>
Child.vue
넘길 값이 따로 없다면 e만 설정해 주면 되고 emits()을 할 때에도 넘겨줄 값이 없기 때문에 두 번째 인수를 생략해 주면 된다.
<template>
<Child @update:message="receivedMessage = 'update message'" />
<div>{{ receivedMessage || '받은 메시지가 없음' }}</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue';
const receivedMessage = ref('');
</script>
Parent.vue
Ref 타입 설정
<template>
<div>{{ message }}</div>
<div>{{ number }}</div>
<div>{{ numbers }}</div>
<div>{{ languageCode }}</div>
<div>{{ book.title }}</div>
</template>
<script setup lang="ts">
import { Ref, ref } from 'vue'
// 자동 추론: Ref<string>
const message = ref('Hello World!');
// Ref 타입 명시 - 기본 타입
const number: Ref<number> = ref(10);
// Ref 타입 명시 - 배열
const numbers: Ref<number[]> = ref([10, 20]);
// Ref 타입 명시 - 유니온 타입
const languageCode: Ref<"ko" | "en"> = ref('ko');
// Ref 타입 명시 - 객체
interface Book {
title: string;
author?: string;
}
const book: Ref<Book> = ref({
title: 'The Black Cat'
});
</script>
ref의 타입 설정은 Ref<Type>을 사용하여 타입을 설정하면 된다.
Reactive 타입 설정
<template>
<div>{{ book.title }}</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
interface Book {
title: string;
author?: string;
}
const book: Book = reactive({
title: 'The Black cat'
})
</script>
일반 Typescript 객체처럼 타입을 설정하면 된다.
computed 타입 추론
자동 타입 추론
<template>
<p>{{ count }}</p>
<p>{{ doubleCount }}</p>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
const count = ref(10);
// 반환 값으로 타입 추론 - CoumputedRef<number>
const doubleCount = computed(() => {
return count.value * 2;
})
</script>
타입 명시
<template>
<p>{{ count }}</p>
<p>{{ doubleCount }}</p>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
const count = ref(10);
// 타입 명시 - ComputedRef<number>
const doubleCount = computed<number>(() => {
return count.value * 2;
})
</script>
이벤트 핸들러 타입 설정
<template>
<input type="text" @change="handleChange" />
</template>
<script setup lang="ts">
import { Ref, ref } from 'vue'
const data: Ref<string> = ref('');
const handleChange = (e: Event) => {
console.log((e.target as HTMLInputElement).value);
}
</script>
e의 타입을 Event로 설정하고 'as' 키워드로 타입을 명시해 줘야 하는 것 같은데 공식 문서에도 자세한 가이드가 없다.
이 부분은 프로젝트를 진행하면서 필요한 부분을 그때그때 찾아봐야 할 듯하다.