You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:03:22