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

如何在Ajax更新Bootstrap Accordion时保持展开/折叠状态?

解决Bootstrap Accordion每秒重写HTML丢失展开状态的问题

问题根源

你现在每次AJAX请求成功后直接清空整个Accordion再重新生成所有面板,这会彻底销毁原有DOM元素,导致之前的展开状态丢失。你之前尝试保存状态但没成功,主要有两个原因:

  • 可能data_length未正确定义(你的代码里没看到它的来源,应该是dataJson.length)
  • 只给折叠面板加了show类,但没同步更新accordion按钮的状态(Bootstrap的Accordion需要按钮的aria-expanded属性和collapsed类配合才能维持状态)

方案一:修复原有思路,先保存状态再重建

先在清空DOM之前,把每个面板的展开状态保存下来,重建时同步更新面板和按钮的状态:

let statusShow = []; // 不要固定初始长度,根据实际数据动态更新

function getInput() {
    $.ajax({
        url: "./Input",
        type: 'POST'
    })
    .done((data) => {
        let dataJson = JSON.parse(data.replace(/\\'/g, "'"));
        const data_length = dataJson.length; // 正确定义数据长度

        // 第一步:在清空DOM前保存所有面板的展开状态
        statusShow = []; // 重置状态数组
        for (let d = 0; d < data_length; d++) {
            const collapseEl = document.getElementById('collapse' + d);
            if (collapseEl) {
                // 保存是否展开的状态
                statusShow[d] = collapseEl.classList.contains('show');
            } else {
                // 如果是新面板,默认折叠
                statusShow[d] = false;
            }
        }

        // 清空原有内容
        $("#accordionChar").html('');

        // 第二步:重新生成面板,恢复状态
        for (let d = 0; d < data_length; d++) {
            const isExpanded = statusShow[d];
            // 按钮的类:如果展开,移除collapsed类,aria-expanded设为true
            const buttonClass = `accordion-button ${isExpanded ? '' : 'collapsed'} ${changeBgColor(dataJson)} fw-bolder text-dark`;
            const buttonAriaExpanded = isExpanded ? 'true' : 'false';
            // 折叠面板的类:展开就加show
            const collapseClass = `accordion-collapse collapse ${isExpanded ? 'show' : ''}`;

            $("#accordionChar").append(`
                <div class="accordion-item ${changeBgColor(dataJson)} border border-dark">
                    <h2 class="accordion-header border border-dark" id="heading${d}">
                        <button class="${buttonClass}" type="button"
                            data-bs-toggle="collapse" data-bs-target="#collapse${d}"
                            aria-expanded="${buttonAriaExpanded}" aria-controls="collapse${d}">
                            Characteristic ${d}
                        </button>
                    </h2>
                    <div id="collapse${d}" class="${collapseClass}"
                        aria-labelledby="heading${d}">
                        <div class="accordion-body">
                            <div class="row" id="table_info${d}"></div>
                            <div class="row" id="table_content${d}"></div>
                        </div>
                    </div>
                </div>
            `);

            // 更新面板内容
            makeTable(data, d);
        }
    })
    .fail((err) => {
        console.error('请求失败:', err);
    })
    .always(() => {
        setTimeout(getInput, 1000);
    });
};

方案二:增量更新(更高效,推荐)

不要每次都重建整个Accordion,只更新需要变化的内容:

  1. 对比现有面板数量和新数据长度,处理新增/删除的面板
  2. 对已存在的面板,只更新内部的表格内容,保留展开状态
function getInput() {
    $.ajax({
        url: "./Input",
        type: 'POST'
    })
    .done((data) => {
        let dataJson = JSON.parse(data.replace(/\\'/g, "'"));
        const data_length = dataJson.length;
        const $accordion = $("#accordionChar");
        const existingPanels = $accordion.find('.accordion-item').length;

        // 1. 处理面板数量变化:新增或删除面板
        if (data_length > existingPanels) {
            // 新增面板,默认折叠
            for (let d = existingPanels; d < data_length; d++) {
                $accordion.append(`
                    <div class="accordion-item ${changeBgColor(dataJson)} border border-dark">
                        <h2 class="accordion-header border border-dark" id="heading${d}">
                            <button class="accordion-button collapsed ${changeBgColor(dataJson)} fw-bolder text-dark" type="button"
                                data-bs-toggle="collapse" data-bs-target="#collapse${d}"
                                aria-expanded="false" aria-controls="collapse${d}">
                                Characteristic ${d}
                            </button>
                        </h2>
                        <div id="collapse${d}" class="accordion-collapse collapse"
                            aria-labelledby="heading${d}">
                            <div class="accordion-body">
                                <div class="row" id="table_info${d}"></div>
                                <div class="row" id="table_content${d}"></div>
                            </div>
                        </div>
                    </div>
                `);
            }
        } else if (data_length < existingPanels) {
            // 删除多余的面板
            $accordion.find(`.accordion-item:gt(${data_length - 1})`).remove();
        }

        // 2. 更新每个面板的内容,保留展开状态
        for (let d = 0; d < data_length; d++) {
            // 直接更新表格内容,不触动面板结构
            makeTable(data, d);
            // 可选:如果需要更新面板标题或背景色,单独修改对应元素
            $(`#heading${d} .accordion-button`).addClass(changeBgColor(dataJson));
            $(`#accordionChar .accordion-item:eq(${d})`).addClass(changeBgColor(dataJson));
        }
    })
    .fail((err) => {
        console.error('请求失败:', err);
    })
    .always(() => {
        setTimeout(getInput, 1000);
    });
};

关键注意点

  • Bootstrap的Accordion状态由折叠面板的show类和按钮的aria-expanded属性、collapsed类共同控制,两者必须同步,否则会出现状态异常。
  • 增量更新的方式避免了频繁销毁重建DOM,性能更好,也更不容易出现状态丢失的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 15:25:15