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

