2025-04-03- 學習 Vue 的 slots 觀念

2025-04-03- 學習 Vue 的 slots 觀念

JavaScript 系列九:第5課 ── 學習 Vue 的 slots 觀念
課程目標
學習 vue 的 slots
課程內容
來學一下 slots 的用法

https://vuejs.org/guide/components/slots.html
課後作業
這一課作業,請先看一下 Banner 公告元件的用法

https://quasar.dev/vue-components/banner

請使用官方的元件試玩工具:Vue SFC Playground

https://sfc.vuejs.org/

請建立 MyBanner.vue 元件,並支援下列功能
預設的 slot 能夠放入公告內容
action slot 能夠在下一排最右側放入額外內容
rounded 樣式
完成之後,請在 App.vue 之中匯入此元件,並用多個範例證明,有完成上述規格

做出以上功能,你就完成這次的課程目標了!

好的 👍 我來幫你把「Vue 系列九:第5課 ── 學習 Vue 的 slots 觀念」的課程內容與作業完整設計出來。
這一課的目標是理解 slot 的用途,並實際用一個公告元件 (MyBanner.vue) 來體驗。


1. 課程目標

  • 學會 Vue slot 的基本用法(default slot & named slot)
  • 建立可自訂樣式的公告元件 MyBanner.vue
  • 熟悉如何在 App.vue 中匯入並使用 slot

2. MyBanner.vue 範例程式碼

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!-- MyBanner.vue -->
<template>
<div
class="my-banner"
:class="{ rounded: rounded }"
>
<!-- 預設 slot:公告內容 -->
<div class="banner-content">
<slot>這裡是預設公告內容</slot>
</div>

<!-- action slot:額外動作 -->
<div class="banner-action">
<slot name="action"></slot>
</div>
</div>
</template>

<script setup>
defineProps({
rounded: {
type: Boolean,
default: false
}
})
</script>

<style scoped>
.my-banner {
display: flex;
justify-content: space-between;
align-items: center;
background: #f5f5f5;
padding: 12px 16px;
margin: 8px 0;
border: 1px solid #ddd;
}

.my-banner.rounded {
border-radius: 12px;
}

.banner-content {
flex: 1;
}

.banner-action {
margin-left: auto;
}
</style>

3. App.vue 測試範例

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
31
32
33
34
35
<!-- App.vue -->
<template>
<div>
<h2>🎯 Vue slots 練習 ── MyBanner 範例</h2>

<!-- 範例1:只放公告內容 -->
<MyBanner>
🚨 系統將於今晚 12 點維護!
</MyBanner>

<!-- 範例2:放公告內容 + action slot -->
<MyBanner>
📢 新版本已上線,快來體驗!
<template #action>
<button @click="handleClick">詳細資訊</button>
</template>
</MyBanner>

<!-- 範例3:加上 rounded 樣式 -->
<MyBanner rounded>
✅ 已成功完成操作
<template #action>
<a href="#">查看紀錄</a>
</template>
</MyBanner>
</div>
</template>

<script setup>
import MyBanner from './MyBanner.vue'

function handleClick() {
alert('前往詳細資訊頁面')
}
</script>

4. 課後作業驗收條件 ✅

  • 預設 slot 可以放公告文字
  • action slot 可以在右側放入按鈕或連結
  • 支援 rounded 樣式
  • App.vue 裡用多個範例測試

要不要我幫你先把這份程式碼丟到 Vue SFC Playground 的完整範例連結,讓你可以直接打開就看到效果?

我們這一課就是在學習 slot,而 <template #action> 正是 命名插槽 (named slot) 的用法。


1. slot 的基本觀念

  • slot 就像元件裡的「預留位置」。
  • 父元件可以決定要在這個位置放什麼內容。

舉例:

1
2
3
<!-- MyBanner.vue -->
<slot></slot> <!-- 預設 slot -->
<slot name="action"></slot> <!-- 命名 slot -->

這代表 MyBanner 有兩個插槽:

  • 預設插槽:放公告文字
  • 名為 action 的插槽:放按鈕、連結或其他東西

2. <template #action> 的意思

在 Vue 3 中:

  • #action語法糖 (shorthand)
  • 等同於 v-slot:action

所以這兩個寫法一樣:

1
2
3
4
5
6
7
8
9
10
11
12
<MyBanner>
<template #action>
<button>查看</button>
</template>
</MyBanner>

<!-- 等同於 -->
<MyBanner>
<template v-slot:action>
<button>查看</button>
</template>
</MyBanner>

3. 為什麼要用 <template>

因為一個 slot 可能會包含多個元素。
如果不用 <template>,Vue 會不知道「哪些東西是要給 slot 的」。

✅ 正確寫法:

1
2
3
4
5
6
<MyBanner>
<template #action>
<button>確定</button>
<button>取消</button>
</template>
</MyBanner>

❌ 錯誤寫法:

1
2
3
4
<MyBanner>
<button>確定</button>
<button>取消</button>
</MyBanner>

這樣 Vue 會把它們都放到 default slot,而不是 action slot


👉 總結:

  • <template #action> = <template v-slot:action>
  • 它的作用是把 內容傳給 MyBanner 裡的 <slot name="action">