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
相关产品推荐
相关产品推荐

