Vue插槽---slot详解
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、推荐使用场景
场景 | 推荐插槽类型 |
---|---|
卡片、弹窗、布局组件的内容区域 | 默认插槽 |
页面头部、导航、页脚等分区 | 具名插槽 |
列表项、表格单元格、下拉选项等需要自定义内容 | 作用域插槽 |