簡單說,slot 就是讓元件可以「開個洞」,讓你插你要的內容進去。
想像你在用一個「客製化便當盒」的概念:
元件就像是一個便當盒(外殼)
slot 就是這個便當盒中空的地方
使用的人可以決定要放什麼菜(內容)進去
你做的元件內容就是「固定的」!
<!-- 沒有 slot 的元件 -->
<template>
<div>
<h1>我是固定標題</h1>
<p>這段話無法改</p>
</div>
</template>
缺點:你用這元件 10 次,顯示的都是一模一樣的東西。
<!-- 有 slot 的元件 -->
<template>
<div class="card">
<slot></slot> <!-- 這邊可以插內容進來 -->
</div>
</template>
然後你使用時這樣寫:
<Card>
<h1>自訂的標題</h1>
<p>我可以寫任何東西進去</p>
</Card>
這樣你就可以用同一個元件,但每次插入不同的內容!
因為:
1. 默認插槽 (Default Slot)
最常用的情境,就是「直接一個洞」,讓你插東西進去。
子元件:
<template>
<div class="card">
<slot></slot>
</div>
</template>
父元件使用:
<Card>
<p>這裡的文字會被塞進 slot</p>
</Card>
適合:只有一個插槽,讓父元件自由決定要放什麼。
2. 具名插槽 (Named Slot)
就像便當有「主菜區」「副菜區」,你可以精準放東西。
子元件:
<template>
<div class="layout">
<header><slot name="header"></slot></header>
<main><slot></slot></main> <!-- 默認插槽 -->
<footer><slot name="footer"></slot></footer>
</div>
</template>
父元件使用:
<Layout>
<template v-slot:header>
<h1>這是標題</h1>
</template>
<p>這是主要內容</p>
<template v-slot:footer>
<p>這是頁尾</p>
</template>
</Layout>
適合:一個元件需要多個「特定區塊」時。
3. 作用域插槽 (Scoped Slot)
子元件可以把「資料」傳出去,讓父元件決定要怎麼渲染。
子元件 (把 list 資料丟給 slot):
<template>
<ul>
<slot :items="items"></slot>
</ul>
</template>
<script setup>
const items = ['蘋果', '香蕉', '葡萄']
</script>
父元件 (決定如何顯示):
<List>
<template v-slot="{ items }">
<li v-for="fruit in items" :key="fruit">{{ fruit }}</li>
</template>
</List>
適合:子元件有資料,但不確定父元件要怎麼顯示 → 把主導權交給父元件。
4. 動態插槽 (Dynamic Slot)
插槽名稱也可以用變數來決定,超彈性。
子元件:
<template>
<div>
<slot name="title"></slot>
<slot name="content"></slot>
</div>
</template>
父元件 (用變數決定塞哪個 slot):
<DynamicSlot>
<template v-slot:[slotName]>
<p>這是動態插進 {{ slotName }} 的內容</p>
</template>
</DynamicSlot>
<script setup>
const slotName = 'content'
</script>
適合:需要動態決定「要塞哪個 slot」時,例如 tab 切換。
參考資源
https://vuejs.org/guide
https://www.runoob.com/vue3