【Vue.js】 插槽通信——具名插槽通信
目录
- 前景
- 基本语法
- 命名规则
- 默认内容
- 使用建议
- 具体实例
- 父组件 index.vue
- 子组件 Category.vue
- 效果
前景
下面的父子组件代码仍然在Vue.js演练平台直接运行
基本语法
在子组件中定义插槽
<!-- Category.vue -->
<slot name="插槽名称">默认内容</slot>
- 使用
<slot>
标签定义插槽位置 - 通过
name
属性给插槽命名 - 标签内部内容为默认内容(当父组件不提供内容时显示)
在父组件中使用插槽
<!-- App.vue -->
<Category><template #插槽名称><!-- 要插入的内容 --></template>
</Category>
- 使用
<template>
标签包裹要插入的内容 - 使用
v-slot:插槽名称
或简写#插槽名称
指定要插入的插槽
命名规则
- 插槽名称可以是任意有效的JavaScript标识符
- 名称区分大小写
默认内容
- 当父组件不提供插槽内容时,显示子组件中定义的默认内容
- 提供内容时,默认内容会被覆盖
使用建议
- 为插槽取有意义的名称,提高代码可读性
- 合理使用默认内容,增强组件的健壮性
- 可以使用多个
<template>
块为同一个组件提供不同的插槽内容 - 简写语法
#插槽名
比v-slot:插槽名
更简洁
具名插槽的本质:父组件向子组件「精准投喂」内容
当子组件(Category) 需要在多个位置接收不同的父组件内容,并且希望结构化地控制内容的插入位置时使用。
具名插槽可以解决以下场景组件复用的痛点:
具体实例
父组件 index.vue
<template><div class="parent-container"><h3>父组件</h3><div class="categories-container"><Category class="category-item"><template #s2><div class="content-box"><h4>士兵类型</h4><ul><li v-for="s in sodierTypes" :key="s.id">{{ s.name }}</li></ul></div></template></Category><Category class="category-item"><template #s1><div class="content-box"><h4>风景图片</h4><img :src="img_url" alt="风景图片" class="responsive-image" /></div></template></Category><Category class="category-item"><template #s3><div class="content-box"><h4>视频展示</h4><video :src="v_url1" controls class="responsive-video" /></div></template></Category></div></div>
</template><script setup lang="ts">
import { ref, reactive } from 'vue';
import Category from './Category.vue';const v_url1 = ref('https://vod.v.jstv.com/2025/02/04/JSTV_JSGGNEW_1738669283837_9IgYA02_1378.mp4');
const img_url = ref('https://youimg1.c-ctrip.com/target/100n0p000000fnj3g0396.jpg');
const sodierTypes = reactive([{ id: 'zyb', name: '支援兵' },{ id: 'tjb', name: '突击兵' },{ id: 'ylb', name: '医疗兵' },{ id: 'zcb', name: '侦察兵' }
]);
</script>
<style scoped>
.parent-container {padding: 20px;
}.categories-container {display: flex;gap: 20px;margin-top: 20px;flex-wrap: wrap;
}.category-item {flex: 1;min-width: 300px;border: 1px solid #eee;border-radius: 8px;padding: 15px;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}.content-box {display: flex;flex-direction: column;gap: 10px;
}.responsive-image {max-width: 100%;height: auto;border-radius: 4px;}
.responsive-video {width: 100%;border-radius: 4px;
}h4 {margin: 0 0 10px 0;color: #333;
}
ul {list-style: none;padding: 0;margin: 0;
}li {padding: 5px 0;border-bottom: 1px solid #f0f0f0;
}li:last-child {border-bottom: none;
}
</style>
子组件 Category.vue
父组件在template标签中定义的插槽名,子组件使用 name属性与父组件对应插槽绑定。
<template><div>
<slot name="s1"></slot>
<slot name="s2"></slot>
<slot name="s3"></slot></div>
</template>
<script setup lang="ts" name="Category">
</script>
作用:定义了三个具名插槽(s1、s2、s3),作为内容占位符。
特点 | 实现效果 |
---|---|
内容精准投放 | 父组件通过 #s1、#s2、#s3 将不同内容插入子组件的对应位置。 |
组件高度复用 | 同一个 Category 组件通过插槽展示完全不同的内容(列表、图片、视频)。 |
结构清晰 | 子组件负责布局框架,父组件决定具体内容,职责分离。 |
灵活组合 | 父组件可以只填充部分插槽(例如仅用 s1 和 s2,忽略 s3)。 |