基于Node+Express+EJS实现无刷新评论上下赞数据库更新
解决评论点赞/点踩的无刷新更新问题
嘿,我来帮你搞定这个无刷新点赞点踩的功能!咱们从后端接口到前端交互一步步捋清楚,保证能跑通。
第一步:编写后端Express接口(处理数据库更新)
首先你需要新增一个POST接口(别用GET,因为要修改数据),用来接收前端的投票请求,然后操作MySQL更新对应评论的赞/踩数。假设你的评论表叫comments,字段包含id(评论ID)、likes(赞数)、dislikes(踩数),代码可以这么写:
// 处理投票请求的接口 app.post("/api/comment/vote", (req, res) => { // 从请求体里拿评论ID和投票类型(up/down) const { commentId, voteType } = req.body; // 先做参数校验,防止非法请求 if (!commentId || !["up", "down"].includes(voteType)) { return res.status(400).json({ success: false, message: "参数错误,请检查请求" }); } // 根据投票类型确定要更新的字段 const updateField = voteType === "up" ? "likes" : "dislikes"; // 编写SQL:对应字段自增1,where条件锁定目标评论 const updateSql = `UPDATE comments SET ${updateField} = ${updateField} + 1 WHERE id = ?`; connection.query(updateSql, [commentId], (error, updateResult) => { if (error) { console.error("更新投票数失败:", error); return res.status(500).json({ success: false, message: "服务器内部错误" }); } // 检查是否真的有评论被更新(防止评论ID不存在的情况) if (updateResult.affectedRows === 0) { return res.status(404).json({ success: false, message: "目标评论不存在" }); } // 可选:返回更新后的最新赞/踩数,方便前端实时更新显示 connection.query(`SELECT likes, dislikes FROM comments WHERE id = ?`, [commentId], (queryErr, data) => { if (queryErr) { return res.status(500).json({ success: false, message: "获取最新数据失败" }); } res.json({ success: true, likes: data[0].likes, dislikes: data[0].dislikes }); }); }); });
第二步:调整EJS模板(渲染评论和绑定数据)
在渲染评论的EJS代码里,给点赞/点踩按钮加上评论ID和投票类型的自定义属性,方便前端点击时获取关键信息:
<!-- 假设你在循环渲染所有评论 --> <% comments.forEach(comment => { %> <div class="comment-item" data-comment-id="<%= comment.id %>"> <p class="comment-content"><%= comment.content %></p> <div class="vote-buttons"> <!-- 点赞按钮:绑定投票类型up,显示当前赞数 --> <button class="vote-btn" data-vote-type="up">👍 (<%= comment.likes %>)</button> <!-- 点踩按钮:绑定投票类型down,显示当前踩数 --> <button class="vote-btn" data-vote-type="down">👎 (<%= comment.dislikes %>)</button> </div> </div> <% }) %>
第三步:前端JS处理点击事件(无刷新请求)
用Fetch API(或者你熟悉的Axios)发送异步请求,触发后端接口更新数据库,然后实时修改页面上的赞/踩数,不用刷新页面:
// 给所有投票按钮绑定点击事件 document.querySelectorAll(".vote-btn").forEach(btn => { btn.addEventListener("click", async (e) => { // 获取当前按钮的投票类型和对应评论ID const voteType = e.target.dataset.voteType; const commentId = e.target.closest(".comment-item").dataset.commentId; try { // 发送POST请求到后端接口 const response = await fetch("/api/comment/vote", { method: "POST", headers: { "Content-Type": "application/json", // 如果你的应用有用户登录,记得加CSRF令牌!可以用csurf中间件生成,这里先省略 }, body: JSON.stringify({ commentId, voteType }) }); const result = await response.json(); if (result.success) { // 更新页面上的赞/踩数显示 const upBtn = e.target.closest(".comment-item").querySelector('[data-vote-type="up"]'); const downBtn = e.target.closest(".comment-item").querySelector('[data-vote-type="down"]'); upBtn.textContent = `👍 (${result.likes})`; downBtn.textContent = `👎 (${result.dislikes})`; // 可选:给按钮加个禁用状态,防止用户重复点击 e.target.disabled = true; e.target.style.opacity = "0.6"; } else { alert(result.message); // 提示用户错误信息 } } catch (err) { console.error("投票请求失败:", err); alert("投票失败,请稍后重试"); } }); });
一些额外注意点
- 数据库表初始化:确保
comments表的likes和dislikes字段默认值设为0,新发布的评论初始赞踩数才会是0。 - 防重复投票:上面的代码没处理同一个用户重复投票的问题,如果需要限制,可以新增一张
comment_votes表,记录user_id、comment_id、vote_type,每次投票前先查询用户是否已经投过票。 - CSRF防护:如果你的应用有用户登录功能,一定要加上CSRF防护,Express可以用
csurf中间件,前端请求时把CSRF令牌放在请求头里。
这样一套流程下来,就能实现点击按钮无刷新更新赞/踩数的功能啦!
内容的提问来源于stack exchange,提问作者Nenad Nikoloski
相关产品推荐
相关产品推荐

