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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 02:35:03