Vue3 Composition API实现手风琴组件按需触发API请求
需求可行性分析与实现方案
这个需求完全可行,核心是参考Tabs组件的懒加载逻辑,让Accordion的子组件仅在对应面板被点击展开时才触发API请求,避免初始化时批量加载。
实现思路
- 给Accordion组件维护一个
activePanelKey状态,记录当前处于展开状态的面板唯一标识 - 仅当子面板的标识与
activePanelKey匹配时,才渲染对应的子组件(或触发子组件内部的API调用逻辑) - 点击手风琴面板标题时,更新
activePanelKey为当前面板的标识,触发对应子组件的加载
修改后的Accordion组件代码
<template> <div class="accordion" id="accordionExample"> <div class="accordion-item" v-for="(panel, index) in panels" :key="index"> <h2 class="accordion-header"> <button class="accordion-button" :class="{ collapsed: activePanelKey !== index }" type="button" data-bs-toggle="collapse" :data-bs-target="`#collapse${index}`" @click="togglePanel(index)" > <span v-if="panel.icon" class="me-2"> <component :is="panel.icon" /> </span> {{ panel.label }} </button> </h2> <div :id="`collapse${index}`" class="accordion-collapse collapse" :class="{ show: activePanelKey === index }" data-bs-parent="#accordionExample" > <div class="accordion-body"> <!-- 仅当面板激活时才渲染子组件 --> <component :is="panel.component" v-if="activePanelKey === index" /> </div> </div> </div> </div> </template> <script setup> import { ref } from 'vue' const props = defineProps({ panels: { type: Array, required: true, validator: (value) => { return value.every(item => item.label && item.component) } } }) const activePanelKey = ref(null) // 初始不展开任何面板,也可设置默认展开的面板索引 const togglePanel = (index) => { if (activePanelKey.value === index) { activePanelKey.value = null // 再次点击收起 } else { activePanelKey.value = index // 展开当前面板 } } </script>
子组件示例(含API请求逻辑)
<template> <div>{{ settingsData }}</div> </template> <script setup> import { ref, onMounted } from 'vue' const settingsData = ref(null) const getSettings = async () => { // 模拟API请求 const res = await fetch('/api/settings') settingsData.value = await res.json() } // 组件挂载时触发API,而Accordion仅在激活时才挂载该组件 onMounted(() => { getSettings() }) </script>
逻辑说明
Tabs组件能实现点击才触发API,本质是仅在标签激活时渲染对应子组件;上述Accordion的实现逻辑与之完全对齐,只是交互形式从切换标签变为展开/收起面板,通过v-if控制子组件的渲染时机,从而实现点击面板才触发对应API请求的效果。
内容的提问来源于stack exchange,提问作者R-b-n
相关产品推荐
相关产品推荐

