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

基于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("投票失败,请稍后重试");
    }
  });
});

一些额外注意点

  1. 数据库表初始化:确保comments表的likes和dislikes字段默认值设为0,新发布的评论初始赞踩数才会是0。
  2. 防重复投票:上面的代码没处理同一个用户重复投票的问题,如果需要限制,可以新增一张comment_votes表,记录user_id、comment_id、vote_type,每次投票前先查询用户是否已经投过票。
  3. CSRF防护:如果你的应用有用户登录功能,一定要加上CSRF防护,Express可以用csurf中间件,前端请求时把CSRF令牌放在请求头里。

这样一套流程下来,就能实现点击按钮无刷新更新赞/踩数的功能啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:01:40