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

Bootstrap 4侧边栏菜单刷新后保持展开状态的实现求助

我明白你想要实现Bootstrap 4侧边栏折叠菜单在页面刷新后保持展开状态的需求,你的尝试思路是对的,但原代码存在几个关键问题导致无法正常工作,比如用索引关联状态不够稳定、监听click事件不够精准。下面给你一个更可靠的实现方案:

核心思路

我们不再通过索引来记录菜单状态,而是通过菜单的唯一ID来存储展开状态,这样即使侧边栏菜单结构发生变化,状态也能准确对应。同时利用Bootstrap折叠组件自带的show.bs.collapse和hide.bs.collapse事件来监听状态变化,避免依赖定时器,更精准可靠。

完整实现代码

你的HTML代码无需修改(确保子菜单ul都有唯一ID)

<nav id="sidebar">
 <ul class="list-unstyled components">
 <li class="active">
 <a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
 <i class="fa fa-th-large"></i>
 <span class="nav-label">Dashboards</span>
 </a>
 <ul class="collapse list-unstyled" id="homeSubmenu">
 <li>
 <a href="index.html"><i class="far fa-circle"></i> Dashboard v.1</a>
 </li>
 <li>
 <a href="dashboard_v2.html"><i class="far fa-circle"></i> Dashboard v.2</a>
 </li>
 <li>
 <a href="dashboard_v3.html"><i class="far fa-circle"></i> Dashboard v.3</a>
 </li>
 <li>
 <a href="dashboard_v4.html"><i class="far fa-circle"></i> Dashboard v.4</a>
 </li>
 <li>
 <a href="dashboard_v5.html"><i class="far fa-circle"></i> Dashboard v.5</a>
 </li>
 </ul>
 </li>
 <li>
 <a href="#">
 <i class="fas fa-image"></i>
 <span class="nav-label">Layouts</span>
 </a>
 </li>
 <li>
 <a href="#graphs" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
 <i class="far fa-chart-bar"></i>
 <span class="nav-label">Graphs</span>
 </a>
 <ul class="collapse list-unstyled" id="graphs">
 <li><a href="graph_flot.html"><i class="far fa-circle"></i> Flot Charts</a></li>
 <li><a href="graph_morris.html"><i class="far fa-circle"></i> Morris.js Charts</a></li>
 <li><a href="graph_rickshaw.html"><i class="far fa-circle"></i> Rickshaw Charts</a></li>
 <li><a href="graph_chartjs.html"><i class="far fa-circle"></i> Chart.js</a></li>
 <li><a href="graph_chartist.html"><i class="far fa-circle"></i> Chartist</a></li>
 <li><a href="c3.html"><i class="far fa-circle"></i> c3 charts</a></li>
 <li><a href="graph_peity.html"><i class="far fa-circle"></i> Peity Charts</a></li>
 <li><a href="graph_sparkline.html"><i class="far fa-circle"></i> Sparkline Charts</a></li>
 </ul>
 </li>
 </ul>
</nav>

修改后的jQuery代码

$(document).ready(function() {
    // 定义存储状态的localStorage键名
    const STORAGE_KEY = 'expandedSidebarMenus';

    // 1. 页面加载时恢复菜单展开状态
    function restoreMenuState() {
        const expandedMenus = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
        expandedMenus.forEach(menuId => {
            const $menu = $(`#${menuId}`);
            if ($menu.length) {
                // 展开子菜单
                $menu.addClass('show');
                // 更新父级a标签的aria-expanded属性为true,保持视觉状态一致
                $menu.prev('.dropdown-toggle').attr('aria-expanded', 'true');
            }
        });
    }

    // 2. 监听折叠菜单的展开/收起事件,更新存储状态
    $('.collapse').on('show.bs.collapse', function() {
        const expandedMenus = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
        const menuId = $(this).attr('id');
        if (!expandedMenus.includes(menuId)) {
            expandedMenus.push(menuId);
            localStorage.setItem(STORAGE_KEY, JSON.stringify(expandedMenus));
        }
    });

    $('.collapse').on('hide.bs.collapse', function() {
        const expandedMenus = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
        const menuId = $(this).attr('id');
        const index = expandedMenus.indexOf(menuId);
        if (index !== -1) {
            expandedMenus.splice(index, 1);
            localStorage.setItem(STORAGE_KEY, JSON.stringify(expandedMenus));
        }
    });

    // 初始化时恢复状态
    restoreMenuState();
});

代码关键点说明

  • 用ID关联状态:每个子菜单ul都有唯一ID(比如homeSubmenu、graphs),我们存储这些ID的数组,避免DOM结构变化导致状态错位。
  • 利用Bootstrap折叠事件:show.bs.collapse在菜单开始展开时触发,hide.bs.collapse在菜单开始收起时触发,不需要依赖定时器来处理动画延迟,状态更新更精准。
  • 同步父级按钮状态:展开子菜单时,同时更新父级a标签的aria-expanded属性为true,确保按钮的视觉状态(比如箭头方向)和子菜单状态一致。
  • 容错处理:读取localStorage时如果没有数据,默认用空数组,避免报错。

原代码的问题分析

  1. 监听范围太广:原代码监听所有ul的click事件,容易误触发(比如点击子菜单里的a标签也会触发),导致状态存储错误。
  2. 索引关联不可靠:用数组索引对应菜单,一旦侧边栏新增/删除菜单,索引就会错位,状态无法正确恢复。
  3. 依赖定时器:依赖600ms定时器来等待动画结束,这种方式不够稳定,不同环境下动画时长可能有差异,而用Bootstrap自带事件更可靠。

这样应该就能完美实现你想要的功能了,测试一下刷新页面,之前展开的菜单会保持展开状态~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:19:03