Slot 内容分发
约 601 字大约 2 分钟
布欧-Lewyon
2026-05-15
Slot 是 Vue 组件组合的核心机制——父组件可以向子组件中"投射"任意模板内容。
默认插槽
<!-- Card.vue -->
<template>
<div class="card">
<div class="card-header">
<slot></slot> <!-- 默认插槽:父组件传入的内容在这里渲染 -->
</div>
<div class="card-body">
默认内容
</div>
</div>
</template>
<!-- 使用 -->
<Card>
<h2>标题</h2> <!-- 替换 <slot></slot> -->
</Card>后备内容
<template>
<button type="submit">
<slot>提交</slot> <!-- 父组件不传内容时显示"提交" -->
</button>
</template>具名插槽
<!-- Layout.vue -->
<template>
<div class="layout">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> <!-- 默认插槽(name="default") -->
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<!-- 使用 -->
<Layout>
<template v-slot:header> <!-- 缩写 #header -->
<h1>页面标题</h1>
</template>
<p>主体内容</p> <!-- 隐式使用默认插槽 -->
<template #footer>
<p>版权信息 © 2026</p>
</template>
</Layout>
v-slot:缩写为#:v-slot:header→#header,v-slot:default→#default(或直接写内容)。
作用域插槽
子组件可以向插槽传递数据——让父组件"拿到子组件内部的数据":
<!-- List.vue -->
<script>
export default {
data: () => ({
items: ['苹果', '香蕉', '橘子']
})
}
</script>
<template>
<ul>
<li v-for="(item, index) in items" :key="index">
<slot :item="item" :index="index">{{ item }}</slot>
</li>
</ul>
</template>
<!-- 使用 -->
<List v-slot="slotProps">
<!-- slotProps = { item: '苹果', index: 0 } -->
<strong>{{ slotProps.index }}. {{ slotProps.item }}</strong>
</List>
<!-- 解构写法 -->
<List v-slot="{ item, index }">
<em>{{ index }}: {{ item }}</em>
</List>
<!-- 具名插槽 + 解构 -->
<Layout>
<template #header="{ title }">
<h2>{{ title }}</h2>
</template>
</Layout>动态插槽名
<template>
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
</template>实战案例:表格列自定义
<!-- DataTable.vue -->
<script>
export default {
props: {
columns: Array,
data: Array
}
}
</script>
<template>
<table>
<thead>
<tr>
<th v-for="col in columns" :key="col.key">{{ col.label }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in data" :key="rowIndex">
<td v-for="col in columns" :key="col.key">
<!-- 允许父组件自定义某列的渲染 -->
<slot :name="`col-${col.key}`" :row="row" :value="row[col.key]">
{{ row[col.key] }} <!-- 默认渲染 -->
</slot>
</td>
</tr>
</tbody>
</table>
</template>
<!-- 使用 -->
<DataTable :columns="columns" :data="users">
<template #col-status="{ row }">
<span :class="row.active ? 'active' : 'inactive'">
{{ row.active ? '启用' : '禁用' }}
</span>
</template>
<template #col-action="{ row }">
<button @click="edit(row)">编辑</button>
<button @click="remove(row)">删除</button>
</template>
</DataTable>小结
| 插槽类型 | 语法 | 用途 |
|---|---|---|
| 默认插槽 | <slot> / v-slot:default | 基本内容注入 |
| 具名插槽 | <slot name="header"> / #header | 多区域注入 |
| 作用域插槽 | <slot :item="item"> / v-slot="{ item }" | 子传数据给父 |
| 动态插槽名 | v-slot:[name] | 动态决定注入位置 |
上一节:Props 与 Emits 下一节:v-model 与表单组件绑定
