Props
- 부모 컴포넌트가 자식 컴포넌트에 데이터를 전달할 때 사용하는 방법
<!-- Parent.vue -->
<template>
<Child :message="parentMessage" />
</template>
<script setup>
import Child from "./Child.vue";
const parentMessage = "Hello from Parent";
</script>
<!-- Child.vue -->
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup>
defineProps({
message: String,
});
</script>
옵션
옵션 |
설명 |
예시 |
type |
prop의 타입을 지정 |
type: String, type: [String, Number] |
default |
prop이 전달되지 않았을 때 사용할 기본값을 지정 (객체나 배열은 팩토리 함수로 반환해야 함) |
default: 'Hello', default: () => [] |
required |
prop이 필수인지 여부를 정의 |
required: true |
validator |
prop 값에 대한 커스텀 유효성 검사를 위한 함수 |
validator(value) { return value.startsWith('Hello'); } |
<!-- Parent.vue -->
<template>
<Child :message="message" :items="items" />
</template>
<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
const message = ref("Hello, World"); // 'Hello'로 시작하지 않으면 경고 발생
const items = ref([1, "two", 3]); // 배열에 숫자가 아닌 값이 포함되어 있으면 경고 발생
</script>
<!-- Child.vue -->
<template>
<div>
<p>{{ message }}</p>
<p>{{ items }}</p>
</div>
</template>
<script setup>
const props = defineProps({
message: {
type: String,
default: "Default message",
required: true,
validator(value) {
if (!value.startsWith("Hello")) {
console.warn('Message should start with "Hello"');
return false;
}
return true;
},
},
items: {
type: Array,
default: () => [], // 객체나 배열은 함수 형태로 반환
validator(value) {
if (!value.every((item) => typeof item === "number")) {
console.warn("Each item in the array should be a number");
return false;
}
return true;
},
},
});
</script>
특징
- Props Declaration
- <script setup>를 사용하지 않는 컴포넌트에서는 props 옵션을 사용하여 선언
export default {
props: ["foo"],
setup(props) {
console.log(props.foo);
},
};
- Reactive Props Destructure
- (Vue 3.4 이하) foo가 실제 상수로 간주되며 변경되지 않음
- (Vue 3.5 이상) <script setup> 블록 내에서 defineProps에서 구조 분해된 변수를 접근할 때, Vue의 컴파일러가 자동으로 props.를 앞에 추가
const { foo } = defineProps(["foo"]);
watchEffect(() => {
// `foo` 는 컴파일러에 의해 `props.foo` 로 변형
console.log(foo); // console.log(props.foo)
});
- Prop Name Casing
- JavaScript에서 props를 camelCase로 선언
defineProps({
greetingMessage: String,
});
- HTML 템플릿에서 props는 kebab-case로 사용
<MyComponent greeting-message="안녕!" />
- Object Binding
- 인자 없이 v-bind를 사용하여 객체의 모든 속성을 props로 전달 가능
const post = {
id: 1,
title: "Vue와 함께하는 나의 여정",
};
<BlogPost v-bind="post" />
<!-- 위의 예시는 아래와 동일 -->
<BlogPost :id="post.id" :title="post.title" />
- Emit
- 자식에서 props 값을 직접 변경하면 Vue가 경고를 띄움
- 만약 수정이 필요하면 emit을 통해 부모에 알려줘야 함
- 이벤트 명은 update:prop 형식을 써야 함
<!-- Parent.vue -->
<template>
<Child :message="parentMessage" @update:message="parentMessage = $event" />
<!-- $emit으로 커스텀 이벤트를 발생시켜서 파라미터를 넘겼다면, $event는 그 전달된 값 자체가 됨 -->
</template>
<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
const parentMessage = ref("Hello from Parent");
</script>
<!-- Child.vue -->
<template>
<div>
<p>{{ message }}</p>
<button @click="changeMessage">Change Message</button>
</div>
</template>
<script setup>
const props = defineProps({
message: String,
});
const emit = defineEmits(["update:message"]); // event name은 'update:prop' 형식을 써야 함
const changeMessage = () => {
emit("update:message", "Hello from Child!"); // emit(event name, parameter1, parameter2, ...)
};
</script>
출처: 짐코딩, 「Vue3 완벽 마스터: 기초부터 실전까지 - "기본편"」, 인프런
출처: Vue.js