1、什么是 Vue 插槽?
????????Vue 插槽(Slot)?? 是 Vue 提供的一種非常強大且靈活的機制,用于實現:父組件向子組件傳遞一段模板內容(HTML / 組件等),讓子組件在指定位置動態渲染這些內容。
????????可以把插槽理解為:
- 子組件定義了一個 ??“內容占位符”??
- 父組件可以在使用子組件時,?往這個占位符里插入自定義內容
2、插槽的作用
????????在組件化開發中,常常封裝一些可復用的組件,比如:
- Card(卡片)
- Button(按鈕)
- Modal(彈窗)
- Layout(布局)
????????但這些組件內部某些部分的內容可能是不固定的,比如:
- 卡片組件中的內容文本
- 導航欄中的菜單項
- 彈窗中的主體內容
????????這時候,如果寫死組件內部的 DOM 結構,會缺乏靈活性;
?插槽就是用來解決這種“內容動態化”的問題,讓組件更加靈活和可復用!?
3、插槽的基本使用(默認插槽)
? ? ? ? 1、子組件(帶插槽占位符)?ChildComponent.vue
<!-- ChildComponent.vue -->
<template><div class="card"><h3>這是一個卡片標題</h3><!-- 插槽占位符:父組件可以在這里插入任意內容 --><slot></slot></div>
</template><style scoped>
.card {border: 1px solid #ccc;padding: 20px;border-radius: 8px;
}
</style>
? ? ? ? 2、父組件(向子組件傳入內容)
<template><ChildComponent><!-- 這里的內容會被插入到子組件的 <slot> 位置 --><p>這是父組件傳入的內容,會顯示在子組件的插槽位置!</p></ChildComponent>
</template><script setup>
import ChildComponent from './ChildComponent.vue'
</script>
結果:
????????子組件中的?<slot></slot>
?會被替換為父組件寫在?<ChildComponent>
?標簽內部的 HTML 內容。
4、具名插槽(Named Slots)
????????當一個組件中有多個插槽位置時,我們需要給每個插槽起個名字,這就是具名插槽。
? ? ? ? 1、子組件(定義多個具名插槽)BaseLayout.vue
<!-- BaseLayout.vue -->
<template><div class="layout"><header><!-- 具名插槽:header --><slot name="header"></slot></header><main><!-- 默認插槽(沒有名字的) --><slot></slot></main><footer><!-- 具名插槽:footer --><slot name="footer"></slot></footer></div>
</template>
? ? ? ? 2、父組件(向不同插槽傳入內容)
<template><BaseLayout><!-- 往 name="header" 的插槽傳內容 --><template #header><h1>這是頁面頭部</h1></template><!-- 默認插槽(沒有 name 的,直接寫內容也可以) --><p>這是頁面的主要內容區域</p><!-- 往 name="footer" 的插槽傳內容 --><template #footer><p>? 2025 我的網站</p></template></BaseLayout>
</template><script setup>
import BaseLayout from './BaseLayout.vue'
</script>
注意:**#header
?是?<template v-slot:header>
?的簡寫形式(Vue 2.6+ 推薦)?**?
????????Vue 2.6 之前寫法
<template slot="header"><h1>>這是頁面頭部</h1>
</template><template slot="footer"><p>? 2025 我的網站</p>
</template>
5、作用域插槽(Scoped Slots)
????????作用域插槽是一種更高級的插槽用法,允許子組件向父組件傳遞數據,讓父組件可以基于子組件的數據來渲染插槽內容。
????????舉例:
封裝了一個列表組件,列表的數據是由子組件管理的,但每一項的內容希望由父組件自定義。
????????1、子組件(傳遞數據給插槽)UserList.vue
<!-- UserList.vue -->
<template><ul><li v-for="user in users" :key="user.id"><!-- 作用域插槽:將 user 數據傳遞給父組件 --><slot :user="user"></slot></li></ul>
</template><script setup>
import { ref } from 'vue'// 模擬數據
const users = ref([{ id: 1, name: 'Alice' },{ id: 2, name: 'Bob' },{ id: 3, name: 'Charlie' }
])
</script>
? ? ? ? 2、父組件(使用子組件,并接收子組件傳遞的數據)
<template><UserList><!-- 使用 v-slot 或 # 接收子組件傳遞的 user 對象 --><template #default="slotProps"><span>{{ slotProps.user.name }}</span></template></UserList>
</template><script setup>
import UserList from './UserList.vue'
</script>
slotProps
?是一個對象,包含子組件傳遞出來的所有數據(比如這里的?user
)
????????Vue 2.6+推薦的簡寫方式:這樣寫更簡潔,直接解構?user
。
<template><UserList><!-- 簡寫:#default="user" --><template #default="{ user }"><div>ID: {{ user.id }} - Name: {{ user.name }}</div></template></UserList>
</template>
????????或者給插槽起名字(比如叫?item
):
????????子組件:
<slot name="item" :user="user"></slot>
????????父組件:
<template #item="{ user }"><div>{{ user.name }}</div>
</template>
6、推薦使用場景
場景 | 推薦插槽類型 |
---|---|
卡片、彈窗、布局組件的內容區域 | 默認插槽 |
頁面頭部、導航、頁腳等分區 | 具名插槽 |
列表項、表格單元格、下拉選項等需要自定義內容 | 作用域插槽 |