3. 创建第一个自定义槽位组件
本章将引导你从零搭建一个带自定义槽位的 BottomNavigation 组件。你将在 Vue 3 + Vite 环境下完成项目初始化、组件注册(全局与局部)以及编写支持默认 slot 和命名 slot 的模板结构。槽位的核心价值在于将“布局占位”与“内容实现”解耦——组件只声明几个空孔位,父组件通过 slot 注入图标、文字、徽标等任意内容。下面按三步完成。
学习前提:确保已安装 Node.js 18+ 和 npm/pnpm。
3.1 项目初始化
使用 Vite 快速创建 Vue 3 + TypeScript 项目:
npm create vite@latest bottom-nav-slot -- --template vue-ts
cd bottom-nav-slot
npm install
安装完成后,进入 src/components/ 目录,创建 BottomNavigation.vue 文件。项目文件夹结构如下:
src/
├── components/
│ ├── BottomNavigation.vue ← 待创建
│ └── HelloWorld.vue
├── App.vue
├── main.ts
└── ...
3.2 组件注册
BottomNavigation 建议以局部注册方式在父组件中使用,更灵活且便于单元测试。在 App.vue 中:
<script setup lang="ts">
import BottomNavigation from './components/BottomNavigation.vue'
</script>
<template>
<BottomNavigation>
<!-- 内容通过 slot 注入 -->
</BottomNavigation>
</template>
若需要全局注册(例如在插件中),可在 main.ts 中添加:
import { createApp } from 'vue'
import App from './App.vue'
import BottomNavigation from './components/BottomNavigation.vue'
const app = createApp(App)
app.component('BottomNavigation', BottomNavigation)
app.mount('#app')
| 注册方式 | 作用域 | 适用场景 |
|---|---|---|
| 局部注册 | 当前组件 | 按需引入、树摇优化、测试隔离 |
| 全局注册 | 所有组件 | 组件库、全局导航、频繁复用 |
3.3 基本模板结构
在 BottomNavigation.vue 中编写模板,暴露三个槽位:默认 slot(主内容)和两个命名 slot icon、badge。组件只提供 flex 布局容器和语义结构,不渲染具体内容。
<template>
<nav class="bottom-nav">
<div class="nav-item" v-for="item in items" :key="item.key">
<!-- 图标槽位,默认显示占位 -->
<div class="icon-wrapper">
<slot name="icon" :item="item">
<span>📦</span>
</slot>
</div>
<!-- 徽标槽位(可选) -->
<div class="badge-wrapper">
<slot name="badge" :item="item" />
</div>
<!-- 默认槽位,通常用于标签文本 -->
<div class="label-wrapper">
<slot :item="item">
<span>{{ item.label }}</span>
</slot>
</div>
</div>
</nav>
</template>
<script setup lang="ts">
defineProps<{
items: Array<{ key: string; label: string }>
}>()
</script>
<style scoped>
.bottom-nav {
display: flex;
justify-content: space-around;
border-top: 1px solid #ddd;
padding: 8px 0;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.icon-wrapper, .badge-wrapper, .label-wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.badge-wrapper {
position: absolute;
top: -4px;
right: -8px;
}
</style>
这段模板展示了三个槽位如何分工:命名 slot 接收特定内容(图标、徽标),默认 slot 接收未显式指定 name 的内容(标签文本)。每个 slot 都绑定了 :item 作用域变量,父组件可通过 slot-scope 访问导航项数据。
常见错误:如果没有为命名 slot 提供回退内容(如
<span>📦</span>),当父组件未填充时,该区域会渲染为空,可能破坏布局。务必为每个 slot 设计合理的占位内容。槽位原理回顾:Vue 的 slot 机制本质是“编译时内容分发”。组件在模板中用
<slot> 声明孔位,父组件在使用时通过模板内的子节点填充这些孔位。命名 slot 则通过 v-slot:name 定向填充。下图展示了本节创建的组件结构。至此,你已成功创建了第一个包含自定义槽位的 BottomNavigation 组件。接下来的章节将在此基础上深入作用域 slot、样式覆盖、事件传递等进阶技巧。