| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- Vue
- react
- 이벤트버블링
- 백준10815
- 정처기
- 투두리스트
- 백준5086
- 바닐라js
- 정처기실기
- JavaScript
- 백준10798
- 타입스크립트
- 코테
- Vue3
- 정보처리기사
- JS
- 파이썬
- reactrouter
- 정처기필기
- 자바스크립트
- NextJs
- 10815
- 코딩테스크
- 코딩테스트
- 백준
- 백준2501
- 리액트
- styled-components
- TypeScript
- zustand
- Today
- Total
윤시의 블로그
[Vue] Vue.js의 컴포넌트 시스템(props, emit, v-model, slot, provide/inject, teleport) 본문
[Vue] Vue.js의 컴포넌트 시스템(props, emit, v-model, slot, provide/inject, teleport)
yo09 2025. 2. 21. 08:58Vue.js의 컴포넌트 시스템은 애플리케이션을 독립적이고 재사용 가능한 단위로 분리하여 관리하는 데 중요한 역할을 한다. 컴포넌트는 부모-자식 관계를 형성하며, 데이터를 효율적으로 전달하고 이벤트를 처리하는 다양한 방법이 있다. 이번 글에서는 Vue 컴포넌트 심화 개념인 props, emit, v-model, slot, provide/inject, teleport에 대해 알아볼 예정이다.
1. Props : 부모 → 자식 간 데이터 전달
props는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법이다. Vue에서는 단방향 데이터 흐름을 유지하며, 부모에서 자식으로 전달된 데이터는 자식에서 수정할 수 없다. 자식은 부모로부터 받은 값을 읽기만 할 수 있고, 수정은 부모 컴포넌트에서만 가능하다.
주요 특징
- 단방향 데이터 흐름: 부모에서 자식으로만 데이터가 전달된다.
- 읽기 전용: 자식 컴포넌트에서는 받은 데이터를 수정할 수 없다. 부모에서 값이 변경되면 자식에서 자동으로 반영된다.
- 유효성 검사: defineProps()를 사용하여 전달되는 데이터의 타입, 필수 여부, 기본값 등을 정의할 수 있다.
<!-- 부모 컴포넌트 -->
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
<template>
<ChildComponent title="Vue의 Props" :count="10" />
</template>
<!-- 자식 컴포넌트 -->
<script setup>
const props = defineProps({
title: String,
count: Number
});
</script>
<template>
<h2>{{ title }}</h2>
<p>Count: {{ count }}</p>
</template>
- 부모 컴포넌트에서 count 값을 자식에게 전달한다. 자식에서는 count를 읽기만 할 수 있으며, 수정할 수 없다.
📌 props는 단방향 데이터 흐름을 유지해야 한다는 점이 중요하다. 자식에서 값을 변경하려면 emit을 통해 부모에게 변경을 요청해야 한다.
2. Emit : 자식 → 부모로 이벤트 전파
emit은 자식 컴포넌트에서 발생한 이벤트를 부모 컴포넌트로 전달하는 방법이다. Vue에서는 자식에서 부모로 이벤트를 전파하여 부모가 이를 처리할 수 있게 한다.
주요 특징
- 이벤트 전달: 자식에서 발생한 이벤트를 부모로 전달한다.
- 자동 변환: 이벤트 이름은 kebab-case로 작성되며, 자식에서는 camelCase로 호출해도 자동으로 변환된다.
<!-- 부모 컴포넌트 -->
<script setup>
import MyComponent from './MyComponent.vue';
const handleSomeEvent = () => {
console.log('Event received!');
};
</script>
<template>
<MyComponent @some-event="handleSomeEvent" />
</template>
<!-- 자식 컴포넌트 -->
<script setup>
const emit = defineEmits(['someEvent']);
const handleClick = () => {
emit('someEvent');
};
</script>
<template>
<button @click="handleClick">Click me</button>
</template>
- 자식 컴포넌트에서 emit('someEvent')를 호출하면 부모 컴포넌트에서 @some-event="handleSomeEvent"가 실행된다.
📌 emit은 부모와 자식 간의 이벤트 통신을 담당하는 핵심 메커니즘이다. 부모는 자식에서 발생한 이벤트를 듣고 적절히 처리할 수 있다.
3. v-model : 양방향 데이터 바인딩
v-model은 부모와 자식 컴포넌트 간의 양방향 데이터 바인딩을 가능하게 해준다. Vue 3에서는 defineModel()을 사용하여 v-model을 정의할 수 있다. 부모에서 자식으로 데이터를 전달하고, 자식에서 부모로 변경 사항을 반영할 수 있다.
주요 특징
- 양방향 바인딩: 부모와 자식 간의 데이터가 자동으로 동기화된다.
- 여러 개의 v-model: v-model을 여러 번 사용하여 하나 이상의 데이터 바인딩을 할 수 있다.
<!-- 부모 컴포넌트 -->
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const countModel = ref(0);
</script>
<template>
<ChildComponent v-model="countModel" />
</template>
<!-- 자식 컴포넌트 -->
<script setup>
const model = defineModel();
const increment = () => {
model.value++;
};
</script>
<template>
<button @click="increment">Current Value: {{ model }}</button>
</template>
- 부모는 v-model="countModel"로 데이터를 바인딩하고, 자식 컴포넌트에서 model 값을 수정하면 부모 컴포넌트에서 자동으로 반영된다.
📌 v-model은 양방향 데이터 바인딩을 가능하게 하여 부모와 자식 컴포넌트 간의 데이터 변경을 실시간으로 반영할 수 있다.
4. Slot - 부모의 콘텐츠 삽입
slot은 부모 컴포넌트에서 자식 컴포넌트의 특정 위치에 동적으로 콘텐츠를 삽입할 수 있게 해주는 기능이다. 기본 slot과 named slot을 통해 다양한 방식으로 콘텐츠를 전달할 수 있다.
주요 특징
- 기본 슬롯: 자식 컴포넌트에 삽입된 콘텐츠가 그대로 표시된다.
- named slot: 특정 이름을 가진 슬롯에 콘텐츠를 전달할 수 있다.
<!-- 부모 컴포넌트 -->
<template>
<ChildComponent>
<p>이 부분은 부모에서 전달한 내용입니다.</p>
</ChildComponent>
</template>
<!-- 자식 컴포넌트 -->
<template>
<h2>Child Component</h2>
<slot></slot> <!-- 부모에서 전달한 콘텐츠 삽입 -->
</template>
- 부모가 ChildComponent에 내용을 넣으면, 자식은 <slot></slot>을 통해 그 내용을 표시한다.
📌 slot은 부모-자식 컴포넌트 간 콘텐츠 삽입을 가능하게 하여 동적인 UI 구성에 유용하다.
5. Provide / Inject - 전역 속성 공유
provide와 inject는 부모-자식 관계를 넘어서 컴포넌트 간 데이터 공유를 가능하게 한다. 특히 계층이 깊어지면 prop drilling 문제를 해결하는 데 유용하다.
주요 특징
- provide: 부모 컴포넌트에서 하위 컴포넌트로 데이터를 제공한다.
- inject: 자식 컴포넌트에서 부모 컴포넌트가 제공한 데이터를 받아서 사용할 수 있다.
<!-- 부모 컴포넌트 -->
<script setup>
import { provide } from 'vue';
provide("theme", "dark");
</script>
<template>
<ChildComponent />
</template>
<!-- 자식 컴포넌트 -->
<script setup>
import { inject } from 'vue';
const theme = inject("theme");
</script>
<template>
<p>현재 테마: {{ theme }}</p>
</template>
- 부모는 provide()를 통해 theme를 제공하고, 자식은 inject()로 이를 받아 사용한다.
📌 provide/inject는 중간 컴포넌트가 없이 부모에서 자식으로 데이터를 제공하고 받을 수 있어, prop drilling 문제를 해결한다.
6. Teleport - DOM 위치 이동
teleport는 Vue 3에서 추가된 기능으로, 현재 컴포넌트 구조와 관계없이 원하는 DOM 위치에 요소를 렌더링할 수 있게 해준다. 예를 들어, 모달을 body 태그 내에 렌더링하고 싶을 때 유용하다.
<template>
<Teleport to="body">
<div class="modal">모달 창입니다.</div>
</Teleport>
</template>
<style>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
}
</style>
- Teleport는 body 태그에 modal을 렌더링하므로, 컴포넌트의 구조와 관계없이 원하는 위치에 모달을 표시할 수 있다.
📌 teleport는 DOM 구조를 변경하지 않고, 원하는 위치에 요소를 렌더링할 수 있도록 해준다.
'Vue' 카테고리의 다른 글
| [Vue] Vue의 반응형 API : 데이터 바인딩 (0) | 2025.02.18 |
|---|