Slot은 컴포넌트 외부에서 컨텐츠를 전달받아, 전달 받은 컨텐츠를 노출하고자 할 때 사용합니다.
// 부모 컴포넌트
<template lang="">
<main>
<FancyButton>Click</FancyButton>
</main>
</template>
<script>
import FancyButton from './FancyButton.vue'
export default {
components: {
FancyButton,
},
setup() {
return { }
},
}
</script>
<style lang=""></style>
FancyButton이라는 자식 컴포넌트에 Click이라는 문자열 텍스틑 전달하였습니다.
// FancyButton
<template lang="">
<buttton class="fancy-btn">
<slot></slot>
</buttton>
</template>
<script>
export default {}
</script>
<style>
.fancy-btn {
color: #fff;
background: linear-gradient(315deg, #42d392 25%, #647eff);
border: none;
padding: 5px 12px;
margin: 5px;
border-radius: 8px;
cursor: pointer;
}
</style>
FancyButton template 내부의 slot 태그가 전달 받은 컨텐츠로 교체됩니다. 위 보기에서는 문자열이지만, html 태그도 전달 가능합니다.
자식 태그에 여러 개의 slot이 존재하는 경우, slot별로 name을 설정가능합니다.
자식 컴포넌트 (ChildComponent.vue)
<template>
<div class="card">
<!-- 기본 슬롯 (이름이 없는 슬롯) -->
<div class="header">
<slot></slot>
</div>
<!-- 이름이 지정된 슬롯: 'content' -->
<div class="content">
<slot name="content"></slot>
</div>
<!-- 이름이 지정된 슬롯: 'footer' -->
<div class="footer">
<slot name="footer"></slot>
</div>
</div>
</template>
<script>
export default {
name: "ChildComponent"
};
</script>
<style scoped>
.card {
border: 1px solid #ccc;
padding: 10px;
border-radius: 4px;
}
.header, .content, .footer {
margin-bottom: 10px;
}
</style>
부모 컴포넌트 (ParentComponent.vue)
<template>
<ChildComponent>
<!-- 기본 슬롯: 이름이 없는 슬롯에 콘텐츠를 전달 -->
<h1>Header Slot Content</h1>
<!-- 이름이 'content'인 슬롯에 콘텐츠를 전달 -->
<template v-slot:content>
<p>This is the content for the content slot.</p>
</template>
<!-- 이름이 'footer'인 슬롯에 콘텐츠를 전달 -->
<template v-slot:footer>
<button>Footer Button</button>
</template>
</ChildComponent>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
}
};
</script>
Render Scope는 Vue에서 슬롯(Slot)과 관련된 개념으로, 특히 슬롯을 통해 전달된 콘텐츠가 어느 범위(scope)에서 렌더링되는지를 의미합니다. 주로 Scoped Slot과 연결되어 사용되며, 기본적인 개념은 슬롯에 전달된 데이터가 부모 컴포넌트에서 어떻게 접근되고 사용되는지를 이해하는 데 도움이 됩니다.
Vue에서 슬롯은 기본적으로 부모 컴포넌트의 스코프에서 렌더링됩니다. 즉, 부모 컴포넌트는 자식 컴포넌트에 있는 슬롯 영역을 제어하거나 커스터마이즈할 수 있고 그 내용은 부모의 데이터와 메소드에 접근할 수 있습니다.
<!-- 부모 컴포넌트 -->
<template>
<ChildComponent>
<p>{{ parentMessage }}</p> <!-- 부모의 데이터에 접근 가능 -->
</ChildComponent>
</template>
<script>
export default {
data() {
return {
parentMessage: "Hello from Parent!"
}
}
}
</script>
<!-- 자식 컴포넌트 -->
<template>
<div>
<slot></slot>
</div>
</template>
위 코드에서 ChildComponent에 전달하는 slot에 부모의 데이터인 parentMessage가 사용되고 있습니다. 이 경우,
<p>{{ parentMessage }}</p>
는 부모 컴포넌트의 스코프에서 렌더링된다라고 표현합니다. 즉, 슬롯 안의 내용은 부모 컴포넌트의 데이터에 접근할 수 있습니다.
Scoped Slot은 자식 컴포넌트에서 자식의 데이터를 부모로 전달할 때 사용됩니다. 이때, 자식 컴포넌트는 자신의 데이터를 슬롯을 통해 부모에게 제공하고, 부모는 그 데이터를 활용할 수 있게 됩니다. 이 때, 자식 컴포넌트에서 제공된 데이터를 슬롯의 스코프에서 렌더링하는 것입니다.
<!-- 자식 컴포넌트 -->
<template>
<div>
<slot :item="item"></slot> <!-- 자식의 데이터를 슬롯으로 전달 -->
</div>
</template>
<script>
export default {
data() {
return {
item: "Data from Child"
}
}
}
</script>
<!-- 부모 컴포넌트 -->
<template>
<ChildComponent>
<template v-slot:default="{ item }">
<!-- 자식의 데이터를 부모 컴포넌트에서 사용 -->
<p>{{ item }}</p>
</template>
</ChildComponent>
</template>
참고: v-slot:default은 default slot을 의미합니다(Named slot에서 배운 내용).