Slot이란?
부모 컴포넌트에서 자식컴포넌트를 사용할 때 컨텐츠를 전달할 수 있는데 이 때 사용하는 것이 <slot> 이다.
예를들어
<!-- 자식 컴포넌트 -->
<button class="fancy-btn">
<slot></slot>
</button>
HTML
복사
<!-- 부모 컴포넌트 -->
<FancyButton>
클릭하기!
</FancyButton>
HTML
복사
최종적으로 렌더링되는 모습은
<button class="fancy-btn">클릭하기!</button>
HTML
복사
이런식으로 내부 컨텐츠를 자식 컴포넌트에게 제공할 수 있다.
slot name 지정
그리고 <slot>에 name을 적용하여 내가 원하는 slot에 원하는 컨텐츠 전달도 가능하다.
<!-- 자식 컴포넌트 : AppCard.vue -->
<div>
<slot name="header">#Header</slot>
</div>
<div>
<slot name="content1">#Title</slot>
<slot>#Content</slot> <!-- name을 지정하지 않을경우 기본은 default이다. -->
</div>
<div>
<slot name="footer">#Footer</slot>
</div>
HTML
복사
<!-- 부모 컴포넌트 -->
<AppCard>
<template v-slot:header>제목</template>
<template v-slot:[slotArgs]>내용1</template> <!-- slot이름은 동적으로 적용도 가능하다. -->
<template v-slot>내용2</template> <!-- name을 지정하지 않을 경우 기본은 default이다. -->
<template #footer>시간</template> <!-- slot의 단축표현으로 #을 사용할 수 있다. -->
</AppCard>
<script setup>
import AppCard from './AppCard.vue';
const slotArgs = ref('content1');
</script>
HTML
복사
최종적으로 렌더링은 아래와 같이 될 것이다.
<div>
제목
</div>
<div>
내용1
내용2
</div>
<div>
시간
</div>
HTML
복사
자식에서 부모로 데이터 전달
자식 컴포넌트에서 정의한 데이터를 부모 컴포넌트로 slot을 이용해서 전달할 수 있다.
<!-- 자식 컴포넌트 : AppCard.vue -->
<div>
<slot name="content3" content-message="내용3"></slot>
</div>
HTML
복사
<!-- 부모 컴포넌트 -->
<AppCard>
<template #content3="{ contentMessage }">
{{ contentMessage }}
</template>
</AppCard>
HTML
복사
자식 컴포넌트에서 전달한 내용3 을 부모 컴포넌트에서 구조 분해 할당을 통해서 전달받아서 표현 할 수 있다.
렌더링 여부 결정
만약 slot이 정의되지 않았다면 아래와 같이 v-if를 통해 렌더링 여부를 결정할 수 도 있다.
<!-- 자식 컴포넌트 : AppCard.vue -->
<div>
<slot name="content1"></slot>
<slot name="content2"></slot>
<slot v-if="$slots.content3" name="content3"></slot>
</div>
HTML
복사
<!-- 부모 컴포넌트 -->
<AppCard>
<template v-slot:content1>내용1</template>
<template v-slot:content2>내용2</template>
</AppCard>
HTML
복사
이렇게 되어있을 경우 content1, content2만 데이터가 상속 받고 content3은 정의되지 않았기 떄문에 렌더링이 되지 않아 최종적으로 아래와 같이 렌더링 된다.
<div>
내용1
내용2
</div>
HTML
복사