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

如何将HTML按钮与Express服务器DELETE路由关联并刷新页面?

问题与解决方案:Express删除实验后页面不更新的处理

问题场景

我有一个Express服务器,删除实验的路由位于admin.js内,完整路径为/admin/experiments/:expId。服务器端代码如下:

router.route('/experiments/:expId')
    .delete(tokens.verifyToken, adminValidator.isAdmin, (req, res) => {
        const experimentId = req.params.expId;
        const db = req.db;
        db.removeExperiment(experimentId);
        renderExperiments(req, res, db);
    })

function renderExperiments(req, res, db) {
    let allExps = expStandard.getAllExperiments(db);

    res.render('adminExperiments', {
        allExps: allExps,
        approved_flag: APPROVED_EXPERIMENT,
        pending_flag: PENDING_EXPERIMENT
    });
}

客户端脚本adminExperiments.js绑定了删除按钮的点击事件,但调用fetch发送DELETE请求后,虽然返回200状态,页面却没有更新:

document.addEventListener('DOMContentLoaded', registerDeleteExpListeners);

function registerDeleteExpListeners() {
    let deleteButtons = document.querySelectorAll('.btn_exp_delete');
    for (b of deleteButtons) {
        b.addEventListener("click", deleteExperiment);
    }
}

async function deleteExperiment(event) {
    // ???
}

需要实现点击删除按钮后,调用Express路由删除实验,并显示更新后的实验列表。

原因分析

用fetch发送DELETE请求时,服务器会执行删除操作并返回渲染后的adminExperiments页面HTML,但fetch只会获取这个响应内容,不会自动替换当前页面的DOM或触发页面跳转,所以看不到页面更新。

解决方案

方案1:删除成功后刷新页面(最简单)

直接在请求成功后刷新当前页面,让浏览器重新加载最新的实验列表页面:

async function deleteExperiment(event) {
    // 阻止按钮默认行为(若按钮为表单提交类型)
    event.preventDefault();
    
    // 获取按钮绑定的实验ID(需在EJS模板中给按钮添加data-exp-id属性)
    const expId = event.target.dataset.expId;
    if (!expId) return;

    try {
        const response = await fetch(`/admin/experiments/${expId}`, {
            method: 'DELETE',
            // 若启用CSRF防护,需添加对应头部,示例:
            // headers: {
            //     'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
            // }
        });

        if (response.ok) {
            // 刷新页面加载最新列表
            window.location.reload();
        } else {
            alert('删除实验失败,请重试');
        }
    } catch (error) {
        console.error('删除请求出错:', error);
        alert('删除请求出错,请检查网络连接');
    }
}

EJS模板中需给删除按钮添加data-exp-id属性:

<button class="btn_exp_delete" data-exp-id="<%= exp.id %>">删除</button>

方案2:无刷新更新页面内容

如果不想刷新整个页面,可以获取服务器返回的HTML,替换当前页面的实验列表区域:

async function deleteExperiment(event) {
    event.preventDefault();
    const expId = event.target.dataset.expId;
    if (!expId) return;

    try {
        const response = await fetch(`/admin/experiments/${expId}`, {
            method: 'DELETE',
            // 可选:添加CSRF令牌等头部
        });

        if (response.ok) {
            // 获取服务器返回的新页面HTML
            const newHtml = await response.text();
            // 解析HTML并提取实验列表容器
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = newHtml;
            const newTableContainer = tempDiv.querySelector('#experiments-table-container');
            
            if (newTableContainer) {
                // 替换当前页面的列表容器
                document.querySelector('#experiments-table-container').replaceWith(newTableContainer);
                // 重新注册新按钮的事件监听器
                registerDeleteExpListeners();
            }
        } else {
            alert('删除实验失败,请重试');
        }
    } catch (error) {
        console.error('删除请求出错:', error);
        alert('删除请求出错,请检查网络连接');
    }
}

EJS模板中需给实验列表容器添加ID:

<div id="experiments-table-container">
    <table>
        <!-- 实验表格内容 -->
    </table>
</div>

额外注意事项

  • CSRF防护:若Express应用启用了CSRF防护,必须在DELETE请求的headers中携带CSRF令牌,否则会被服务器拒绝。
  • 异步操作顺序:如果db.removeExperiment是异步方法,需等待它执行完成后再调用renderExperiments,避免渲染旧数据,示例:
    await db.removeExperiment(experimentId);
    renderExperiments(req, res, db);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:53:14