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

Vue3+Nuxt3手风琴组件:实现面板显隐的高度平滑动画

Vue3/Nuxt3 手风琴组件实现平滑高度过渡动画

你的手风琴功能正常但缺少高度过渡效果,核心问题是直接用v-if会瞬间添加/移除DOM元素,无法触发CSS过渡。下面是修改后的完整组件代码,可实现平滑的展开/收起动画:

修改后的组件SFC代码

<script setup lang="ts">
const props = defineProps({
  panels: { type: Array, required: true },
})

const current = ref(1)
// 存储每个面板的内容实际高度
const panelHeights = ref<Record<number, number>>({})

function toggleAccordion(index: number) {
  current.value = current.value === index ? 0 : index
}

// 获取面板内容的真实高度
const setPanelHeight = (panelId: number, el: HTMLElement) => {
  if (el) {
    panelHeights.value[panelId] = el.scrollHeight
  }
}
</script>

<template>
  <div v-for="panel in panels" :key="panel.id" class="accordion-item">
    <!-- 手风琴标题栏 -->
    <div 
      class="d-flex flex-row p-4 cursor-pointer bg-gray-200" 
      @click.prevent="toggleAccordion(panel.id)"
    >
      <div v-if="panel.icon">{{ panel.icon }}</div>
      <div class="flex-grow-1">
        <h4 class="mb-0">{{ panel.title }}</h4>
      </div>
      <div>
        <i v-if="panel.id === current" class="ki-outline ki-minus fs-4 text-gray-800"></i>
        <i v-else class="ki-outline ki-plus fs-4 text-gray-800"></i>
      </div>
    </div>

    <!-- 带过渡效果的面板内容 -->
    <Transition name="accordion">
      <div 
        class="accordion-content p-4 overflow-hidden"
        :style="{ height: panel.id === current ? `${panelHeights[panel.id]}px` : '0' }"
        ref="el"
        @update:model-value="setPanelHeight(panel.id, $el)"
      >
        <slot :name="panel.id"></slot>
      </div>
    </Transition>
  </div>
</template>

<style scoped>
.accordion-content {
  transition: height 0.3s ease;
}

/* 过渡状态类,强化动画逻辑 */
.accordion-enter-from,
.accordion-leave-to {
  height: 0 !important;
}

.accordion-enter-active,
.accordion-leave-active {
  transition: height 0.3s ease;
}
</style>

关键修改说明

  • 替换v-if为动态高度绑定:不再直接销毁/创建DOM,而是通过修改height属性控制显示隐藏,配合CSS过渡实现平滑动画。
  • 获取内容真实高度:通过scrollHeight获取每个面板内容的实际高度,确保展开时完全显示内容,避免截断。
  • Vue Transition组件:用<Transition>包裹内容,结合自定义CSS过渡类,精准控制动画的进入和离开状态。
  • CSS过渡配置:给.accordion-content添加transition: height 0.3s ease,可调整0.3s来修改动画速度。

组件使用方式不变

<accordion :panels="panels">
  <template #1>
    this is one
  </template>
  <template #2>
    this is two
  </template>
  <template #3>
    this is three
  </template>
</accordion>

面板数据保持不变

const panels = [
  {id:1,title:'Test Accordion 1',icon:'',},
  {id:2,title:'Test Accordion 2',icon:'',},
  {id:3,title:'Test Accordion 3',icon:'',},
]

内容的提问来源于stack exchange,提问作者Prof Nami

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 04:52:41