Vue 具名插槽 (Named Slots) 詳解:輕鬆管理元件中的多個預留位置
當您開發的 Vue 元件結構較為複雜(例如:包含頁首、頁尾與側邊欄的 Layout 元件)時,單一的 預設插槽 已不足夠。這時就需要使用 具名插槽 (Named Slots) 來精準指定內容的填入位置。
使用具名插槽,您不需要擔心 HTML 的先後順序或 CSS 版面配置,只要將內容分配給對應的名稱,子元件就會自動將它們安置在正確的預定義位置。
具名插槽實作步驟
子元件:定義具名插槽 name
元件中分別給予 <slot> 定義唯一的 name 屬性,例如:foot、extra。
<!-- /components/Card.vue -->
<template>
<div class="card">
<div class="card-head">
<img class="card-image" src="https://picsum.photos/320/180" alt="">
</div>
<div class="card-body">
<h2 class="card-title">卡片標題</h2>
<p class="card-description">
卡片描述~卡片描述~卡片描述~卡片描述~片描述~
</p>
</div>
<div class="card-foot">
<slot name="foot"></slot>
</div>
<div class="card-extra">
<slot name="extra"></slot>
</div>
</div>
</template>父元件:使用 v-slot 或 # 語法傳入內容
在父元件呼叫時,必須使用 <template> 標籤並配合 v-slot 指令來對準目標插槽。
標籤中加入指定插槽的名稱,指定名稱的方式有二:
- 標準語法:
v-slot:foot。 - 簡寫語法:
#foot。
<!-- /views/Slot.vue -->
<template>
<card>
<template #foot>
<input type="button" value="click">
</template>
</card>
</template>v-slot 只能寫在兩個地方
v-slot 與 # 只能出現在 元件標籤 或 <template> 標籤 上。寫在一般的 <div> 上不會生效,這也是為什麼具名內容都要用 <template> 包起來。
與預設插槽混用
未被 <template> 包起來的內容,會自動歸入名為 default 的預設插槽:
<template>
<Card>
<!-- 這段沒有指定名稱,會進入 default 插槽 -->
<p>我是主要內容</p>
<template #foot>
<button>送出</button>
</template>
</Card>
</template>模板一旦同時存在具名內容,建議把預設內容也 明確寫成 <template #default>,讓每段內容的歸屬一目瞭然,也避免日後有人在中間插入節點時發生誤判。
渲染順序由誰決定?
這是具名插槽最方便的一點:父元件的撰寫順序完全不影響畫面順序。
<template>
<Card>
<!-- 雖然 foot 寫在前面…… -->
<template #foot><button>送出</button></template>
<template #extra><small>備註</small></template>
</Card>
</template>實際位置仍以子元件模板中 <slot> 出現的地方為準。版面配置的責任留在子元件,父元件只負責提供內容,這正是 插槽帶來的關注點分離。
為什麼要使用具名插槽?
結構化版面配置
讓元件的內部結構(HTML/CSS)由子元件控制,而具體內容(數據/按鈕)由父元件決定。
語意清晰
透過 foot、header、sidebar 等名稱,程式碼的閱讀性大幅提升。
靈活性提升
父元件可以選擇性地填入部分插槽,未填入的部分則可以顯示子元件設定的預設內容。
若希望 沒填內容時連外層的包裝標籤都不要出現,可以搭配 條件插槽;若插槽名稱需要由變數決定,則可參考 動態插槽。
常見問題
v-slot 與 # 有什麼差別?
沒有功能差別,# 是 v-slot 的縮寫。v-slot:foot 等於 #foot,實務上多數專案採用縮寫寫法。
具名插槽一定要包在 template 標籤裡嗎?
是的,v-slot 只能寫在元件標籤或 <template> 標籤上。要把內容指定給某個具名插槽,就必須用 <template> 搭配 v-slot 或 # 語法包起來。
父元件內容的撰寫順序會影響畫面順序嗎?
不會。畫面順序完全由子元件模板中 <slot> 的位置決定,父元件即使把頁尾內容寫在最前面,仍然會渲染在子元件安排的位置。
具名插槽可以和預設插槽混用嗎?
可以。沒有被 <template> 包起來的內容會自動歸入預設插槽,但當模板同時存在具名內容時,建議把預設內容也用 <template #default> 明確包起來,避免歸屬混淆。
父元件沒有填某個具名插槽會怎樣?
該插槽會顯示子元件寫的預設內容,若沒有預設內容就什麼都不渲染。但包在外層的 HTML 標籤仍然存在,若連標籤都想移除,需要搭配 條件插槽 的寫法。