
本文介绍如何在 vue 3 组合式 api 中,将具名插槽(如 `v-slot:slides`)传入的多个独立 vnode 动态渲染到 swiperslide 组件内,核心是利用 `
在构建可复用轮播组件(如 MyCarousel)时,常需兼顾灵活性与封装性:既允许父组件以原生 HTML 形式声明幻灯片内容(便于 Blade 模板集成),又能在 Vue 层自动将其转换为 Swiper 所需的 <swiper-slide> 结构。关键挑战在于——插槽返回的是一个 VNode 数组(而非字符串或 DOM 元素),而 v-for 遍历后每个 slide 是一个完整的 VNode 对象,不能直接写入模板作为 HTML 字符串,也不能用 v-html 渲染。
正确解法是使用内置的 <component> 标签配合 :is 动态绑定:
<template>
<div>
<swiper>
<swiper-slide
v-for="(slide, index) in slots.slides()"
:key="index"
>
<component :is="slide" />
</swiper-slide>
</swiper>
</div>
</template>✅ 这里 :is="slide" 并非传入组件名字符串,而是直接绑定 Vue 编译后的 VNode 实例——Vue 会自动将其“挂载”并渲染为真实 DOM 子树。这是 Vue 3 插槽高级用法的标准实践,适用于任何需要解构、重组插槽内容的场景。
⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- slots.slides() 返回的是函数,调用后才得到 VNode 数组,因此 v-for 中必须写 slots.slides()(带括号);
- 每个 slide 是独立 VNode,自带响应式上下文,无需额外 h() 或 createVNode 封装;
- 若插槽内容含响应式数据或事件监听器(如 <div @click="handleClick">),它们将完整保留并正常工作;
- 建议为 v-for 添加 :key="index"(或更优的唯一标识),避免 VNode 复用导致状态错乱;
- 不要尝试用 v-html 或 innerHTML 处理 slide,这将丢失响应式与事件绑定,且存在 XSS 风险。
最终,你的 Blade 模板保持简洁语义化:
<my-carousel>
<template v-slot:slides>
<div class="slide">Slide 1 — <button @click="log('one')">Log</button></div>
<div class="slide">Slide 2 — {{ currentTime }}</div>
</template>
</my-carousel>所有交互逻辑、响应式更新和生命周期钩子均原样生效——这就是 Vue 插槽 + 动态组件协同带来的强大抽象能力。










