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

MEN栈EJS嵌入jQuery报$未定义 点赞计分功能异常排查

问题根因
  • 核心错误:将jQuery前端交互代码写在了EJS的<% %>服务端执行标签内。这部分代码是Express在服务端渲染页面时于Node环境运行的,Node环境没有加载浏览器端jQuery,必然触发$ is not defined报错。jQuery事件逻辑属于浏览器端代码,必须放在普通<script>标签中,在客户端加载执行。
  • HTML规范违反:循环生成多个帖子条目时重复使用相同id(plus/minus/score),id属性要求全局唯一,重复id会导致JS无法正确匹配目标元素。
  • 属性书写笔误:点赞按钮写为is="plus",并非id="plus",即使逻辑位置正确也无法被选中。
  • 作用域错误:代码中使用的relevance、myBoolean都是服务端模板变量,前端点击事件触发时无法访问这些变量。
修正实现

1. 调整模板DOM结构

将重复id替换为class,给元素补充自定义数据属性存储必要信息,修正按钮属性笔误,循环部分对应代码修改如下:

<div class="carousel-item" style="text-align: justify" >
  <div class="row">
    <h2><%= questions[i].title %></h2>
    <p><%= questions[i].body %></p>
  </div>
  <div class="row" style="width: 100%; height: 90px; white-space: nowrap; overflow-x: auto;">
    <p style = "display: inline-block; width: 70%; height: 100%;"><strong>Posted by: </strong><%= questions[i].userid.username %> on <%= questions[i].datePosted.toDateString() %> </p>
    <button class="submit-btn" style = "display: inline-block; width: 30%; height: 50%; border-radius: 5px; background-color:darkcyan" type="submit">View Responses</button>
  </div>
  <!-- 投票区域加类名和题目id数据属性 -->
  <div class="row vote-area" data-qid="<%= questions[i]._id %>" style="width: 100%; height: 90px; white-space: nowrap; overflow-x: auto;">
    <!-- 按钮用类选择器,加投票值数据属性 -->
    <button style = "display: inline-block; width: 25%; height: 50%; border-radius: 5px" class="vote-btn minus" data-val="-1">-</button>
    <button style = "display: inline-block; width: 25%; height: 50%; border-radius: 5px" class="vote-btn plus" data-val="1">+</button>
    <!-- 分数数字单独包裹,方便更新 -->
    <p style = "display: inline-block; width: 50%; height: 100%;" class="score-text"><strong>  Score: </strong> <span class="score-num"><%= questions[i].upvotes %></span></p>
  </div>
</div>

2. 写入正确的前端jQuery逻辑

将以下代码放在jQuery引入标签之后、页面所有DOM的末尾,不要套在任何EJS<% %>标签内:

<script>
// 等待DOM加载完成后执行
$(document).ready(function() {
  // 用类选择器给所有投票按钮绑定事件
  $('.vote-btn').on('click', function() {
    // 定位到当前按钮所属的投票区域
    const $currentArea = $(this).closest('.vote-area');
    // 防重复投票:如果当前区域已经投过票直接返回
    if ($currentArea.data('voted')) return;
    // 获取当前分数和投票值
    const $scoreEl = $currentArea.find('.score-num');
    let score = parseInt($scoreEl.text());
    const voteVal = parseInt($(this).data('val'));
    // 更新分数
    score += voteVal;
    $scoreEl.text(score);
    // 标记为已投票
    $currentArea.data('voted', true);

    // 后续需要同步到MongoDB时,在这里写AJAX请求即可
    // 示例:
    // $.post('/api/update-vote', {
    //   questionId: $currentArea.data('qid'),
    //   newScore: score
    // })
  })
})
</script>
后续对接数据库提示

分数更新完成后,给后端写一个接收投票参数的接口,前端在分数更新后发POST请求把题目id、最新分数/投票类型传给后端,后端用Mongoose查找到对应题目更新upvotes字段即可,注意要加用户校验,避免恶意刷票。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:12:06