Vue3组合式API多级插槽嵌套折叠组件使用报错与优化方案咨询
Vue3 自定义折叠组件问题解决与优化方案
错误原因
你遇到的语法错误根源是插槽使用不符合Vue规则:
- 当你用
<template #input-group>完全替换组件内部默认结构时,原来承载#button插槽的<div data-bs-toggle="collapse">被移除,#button插槽失去挂载容器。 - 你在父组件的
#input-group插槽内容里直接写<template #button>无效——#button是Collapse组件的顶层插槽,不能嵌套在其他插槽内容中使用,导致Vue模板编译器无法正确解析节点。
修正现有组件的用法
如果要保留最初的组件结构,只能通过替换#button插槽插入自定义内容(包括input-group),但这种方式会让input-group被组件自带的折叠触发div包裹,可能不符合布局需求:
<Collapse css-id="filterCollapse"> <template #button> <div class="input-group"> <input type="text" class="form-control" placeholder="Поиск..."> <button class="btn btn-outline-secondary d-lg-none d-sm-block" type="button"> <i class="bi bi-filter mb-3"></i> </button> </div> </template> <template #content> <!-- 折叠内容 --> </template> </Collapse>
更优的组件设计方案
为了让触发元素(按钮)能灵活嵌入任意层级结构(比如input-group),推荐使用作用域插槽传递折叠所需属性,让父组件完全控制触发元素的位置和结构:
优化后的组件代码
<script setup> defineProps({ cssId: { type: String, required: true } }) </script> <template> <!-- 作用域插槽:传递折叠触发所需的所有属性 --> <slot name="trigger" :triggerAttrs="{ 'data-bs-toggle': 'collapse', 'data-bs-target': `#${cssId}`, 'aria-expanded': 'false', 'aria-controls': cssId }" ></slot> <!-- 折叠内容容器 --> <div class="collapse" :id="cssId"> <slot name="content"></slot> </div> </template>
组件使用方式
在父组件中,通过作用域插槽接收triggerAttrs并绑定到触发按钮上,同时可将按钮放在任意结构内:
<Collapse css-id="filterCollapse"> <template #trigger="{ triggerAttrs }"> <div class="input-group"> <input type="text" class="form-control" placeholder="Поиск..."> <!-- 将折叠属性绑定到按钮上 --> <button class="btn btn-outline-secondary d-lg-none d-sm-block" type="button" v-bind="triggerAttrs" > <i class="bi bi-filter mb-3"></i> </button> </div> </template> <template #content> <!-- 这里放置折叠展开的内容 --> <div class="p-3"> 折叠内容示例 </div> </template> </Collapse>
这种方案的优势:
- 触发元素的结构完全由父组件控制,可嵌入任意层级(比如input-group、导航栏等)。
- 折叠核心逻辑(Bootstrap的data属性)通过组件封装,避免父组件重复编写。
- 插槽职责清晰,
trigger负责触发折叠,content负责展示折叠内容。
内容的提问来源于stack exchange,提问作者Grigory Voevodin
相关产品推荐
相关产品推荐

