Express+EJS待办列表删除任务后页面不更新问题求助
待办列表开发问题排查与解决方案
我的需求
- 使用ExpressJS作为后端开发基础待办列表
- 通过EJS检测用户点击任务的操作
- 使用AJAX将待删除任务项提交至后端
- 后端从列表中删除对应项
- 后端更新前端页面
遇到的问题
- 控制台日志显示任务已删除,但页面未更新
- 后端POST请求中重新渲染index.ejs无效
- 刷新页面后已删除任务才会消失
- AJAX中的console.log无输出
- 后端/delete接口中res.send('hello')无响应
前端EJS代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Proton Planner</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous"> <link rel="stylesheet" href="./styles/styles.css"> </head> <body> <h1>Proton Planner</h1> <% if (locals.tasks) { %> <% for (var ind = 0; ind<locals.tasks.length; ind++) { %> <!-- Change the id and for for each checkbox--> <div class="form-check"> <div class="checker"> <input class="form-check-input" type="checkbox" value="" id="flexCheckDefault<%=ind%>"> </div> <label class="form-check-label" for="flexCheckDefault<%=ind%>"> <%= tasks[ind] %> </label> </div> <% } %> <% } %> <form action="/submit" method="post"> <input placeholder="Add a task" type="text" id="task" name="task" required> <input type="submit" value="Submit"> </form> <!-- JS scripts --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"></script> <script src="./index.js"></script> <script> // AREA OF INTEREST -------------------------------------------------------------- $('.checker').on('click', function() { var itemDel = $(this).next().text().trim(); console.log('Item deleted', itemDel); $.ajax({ type: 'POST', url: '/delete', data: { itemDel, }, success: function(response) { console.log(response); console.log('ajax post success') $.ajax({ type: 'GET', url: '/', success: function(response) { // Handle the successful response here console.log(response); console.log('ajax get success') }, error: function(xhr, status, error) { // Handle errors here console.error(error); } }) }, error: function(xhr, status, error) { // Handle errors here console.error(error); } }) }) </script> </body> </html>
后端ExpressJS代码
// Imports import express from "express"; import bodyParser from "body-parser"; // Constants const app = express(); // MAKE NOTE OF THIS IN TRELLO app.set('view engine', 'ejs') const port = 3000; let taskList = []; // Getting the absolute file path import { dirname } from "path"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); // App.use app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static("public")); // App.get app.get("/", (req, res) => { res.render("index.ejs", { tasks: taskList }) }); // App.post for new task app.post("/submit", (req, res) => { let newTask = req.body["task"] taskList.push(newTask) console.log(taskList) res.render("index.ejs", { tasks: taskList }) }); // Look here ------------------------------------------------------------------- //App.post to delete a task app.post("/delete", (req, res) => { var remItem = req.body.itemDel; console.log(remItem) /* for (var item = 0; item<taskList.length; item++) { if (remItem == taskList[item]) { taskList.splice(item, 1); taskList.push(remItem); console.log(taskList) } }*/ var i = 0; while (i < taskList.length) { if (taskList[i] === remItem) { taskList.splice(i, 1); } else { ++i; }} console.log(taskList); res.send('Hello') //res.render("index.ejs", { tasks: taskList }); }); // App.listen app.listen(port, () => { console.log(`Listening on port ${port}`); });
解决方案
1. 修复动态元素的点击事件绑定
原代码直接给.checker绑定点击事件,但这些元素是EJS动态渲染生成的,页面初始化时不存在,导致点击事件无法触发。改为事件委托方式,确保动态生成的元素也能响应点击:
$(document).on('click', '.checker', function() { var itemDel = $(this).next().text().trim(); console.log('Item deleted', itemDel); // 后续AJAX逻辑保持不变,或按下面步骤修改 })
这一步解决AJAX无输出、后端/delete接口无响应的核心问题,点击事件现在能正确触发,AJAX请求会正常发送。
2. 调整后端响应逻辑,返回JSON格式的任务列表
原后端返回字符串Hello无法满足前端更新页面的需求,改为返回更新后的任务列表JSON数据,让前端可以直接使用:
app.post("/delete", (req, res) => { var remItem = req.body.itemDel; var i = 0; while (i < taskList.length) { if (taskList[i] === remItem) { taskList.splice(i, 1); } else { ++i; } } console.log(taskList); // 返回更新后的任务列表 res.json({ tasks: taskList }); });
3. 前端动态渲染任务列表,无需刷新页面
原代码在AJAX成功后重新请求整个页面但未替换内容,改为直接用后端返回的JSON数据重新渲染任务区域,实现无刷新更新:
$(document).on('click', '.checker', function() { var itemDel = $(this).next().text().trim(); console.log('Item deleted', itemDel); $.ajax({ type: 'POST', url: '/delete', data: { itemDel: itemDel // 显式指定键名,避免解析歧义 }, success: function(response) { console.log('ajax post success', response); // 清空现有任务列表 $('.form-check').remove(); // 重新渲染新的任务列表 if (response.tasks.length > 0) { response.tasks.forEach((task, ind) => { const taskHtml = ` <div class="form-check"> <div class="checker"> <input class="form-check-input" type="checkbox" value="" id="flexCheckDefault${ind}"> </div> <label class="form-check-label" for="flexCheckDefault${ind}"> ${task} </label> </div> `; $('h1').after(taskHtml); }); } }, error: function(xhr, status, error) { console.error(error); } }) })
这一步解决页面未更新、刷新后任务才消失的问题,前端直接用最新数据重新渲染任务区域,无需手动刷新。
4. 关于后端渲染无效的说明
原代码中在/delete接口使用res.render无效,是因为AJAX请求不会自动替换当前页面内容,只有浏览器直接发起的导航请求才会加载渲染后的页面。因此,返回JSON数据让前端动态更新DOM是更适合AJAX场景的方案。
内容的提问来源于stack exchange,提问作者Ahmed Kehinde
相关产品推荐
相关产品推荐

