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

Nuxt 3路由下Bootstrap 5折叠组件状态异常问题

Nuxt3 + Bootstrap5 嵌套折叠组件页面返回后状态异常修复方案

问题根源

浏览器后退时的页面缓存(BF Cache)或Nuxt3的页面复用机制,会导致Bootstrap Collapse组件的内部状态与DOM元素状态脱节。直接手动移除show类的操作,无法同步更新组件关联按钮的aria-expanded属性,进而引发后续点击异常。

修复方案

通过Bootstrap官方API管理折叠组件状态,结合Nuxt的生命周期钩子确保页面返回时状态完全重置:

1. 修改组件代码,使用Vue Refs与Bootstrap Collapse实例

<template>
  <button 
    ref="btn1"
    type="button" 
    class="btn hide-me" 
    data-bs-toggle="collapse" 
    data-bs-target="#collapse1" 
    aria-expanded="false" 
    aria-controls="collapse1"
  >Read More 1</button>
  <div 
    ref="collapse1"
    class="collapse multi-collapse" 
    id="collapse1"
  >
    some text
    <button 
      ref="btn2"
      type="button" 
      class="btn hide-me" 
      data-bs-toggle="collapse" 
      data-bs-target="#collapse2" 
      aria-expanded="false" 
      aria-controls="collapse2"
    >Read More 2</button>
  </div>
  <div 
    ref="collapse2"
    class="collapse multi-collapse" 
    id="collapse2"
  >
    other text
    <button 
      type="button" 
      class="btn" 
      data-bs-toggle="collapse" 
      data-bs-target=".multi-collapse" 
      aria-expanded="false" 
      aria-controls="collapse1 collapse2"
    >Read Less</button>
  </div>
</template>

<script setup>
import { ref, onMounted, onActivated, onUnmounted } from 'vue'
import Collapse from 'bootstrap/js/dist/collapse'

// 绑定DOM元素
const collapse1 = ref(null)
const collapse2 = ref(null)
const btn1 = ref(null)
const btn2 = ref(null)

// 存储Collapse实例
let collapseInstance1 = null
let collapseInstance2 = null

// 重置折叠状态的通用方法
const resetCollapseState = () => {
  // 用官方API隐藏折叠面板
  collapseInstance1?.hide()
  collapseInstance2?.hide()
  // 同步重置按钮的aria状态
  btn1.value.setAttribute('aria-expanded', 'false')
  btn2.value.setAttribute('aria-expanded', 'false')
}

onMounted(() => {
  // 初始化Collapse实例,禁用自动切换避免初始化异常
  collapseInstance1 = new Collapse(collapse1.value, { toggle: false })
  collapseInstance2 = new Collapse(collapse2.value, { toggle: false })
  // 初始状态重置
  resetCollapseState()
})

onActivated(() => {
  // 页面从缓存恢复时触发,确保状态重置
  resetCollapseState()
})

onUnmounted(() => {
  // 组件卸载时销毁实例,避免内存泄漏
  collapseInstance1?.dispose()
  collapseInstance2?.dispose()
})
</script>

<style scoped>
.hide-me {
    opacity: 1;
    height: auto;
    transition: opacity .35s ease;
}

.hide-me[aria-expanded="true"] {
    opacity: 0;
    height: 0;
    overflow: hidden;
    transition: none;
}
</style>

2. 关键说明

  • 使用官方API:通过collapseInstance.hide()而非手动移除show类,确保组件内部状态与DOM完全同步。
  • 利用onActivated钩子:Nuxt3默认开启页面缓存,返回页面时mounted不会重复触发,onActivated会在组件从缓存中激活时执行,保证每次返回都重置状态。
  • 同步按钮状态:手动重置按钮的aria-expanded属性,避免出现按钮显示但状态标记为true的矛盾情况。

可选方案(不推荐)

如果不需要页面缓存,可以在页面组件中添加:

definePageMeta({
  keepalive: false
})

该方法会强制每次返回页面都重新挂载组件,但会牺牲页面切换性能,仅适合简单页面场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:03:31