EJS多表单中AJAX点赞功能仅首个生效问题求助
点赞按钮批量触发首个表单问题解决
问题描述
在EJS页面的多篇帖子中设置点赞按钮后,点击首个按钮时表单提交和视图更新正常,但点击其他按钮时,始终触发首个表单的提交,且仅为首个按钮添加active类。改用类名替代ID后问题依旧,数据库更新正常,问题出在AJAX逻辑和HTML结构上。
原代码
HTML
<form id='like' action="/postLike/<%=blogposts[i]._id%>?_method=PATCH" method="POST"> <% if (blogposts[i].liked == false) {%> <div id='likeBtn' onclick="Like()" class="wrapperHearts"> <svg xmlns="http://www.w3.org/2000/svg" id="Love"><path d="M28.124,15.5615,16.7549,28.6558a1,1,0,0,1-1.51,0L3.876,15.5615A7.6866,7.6866,0,0,1,2.57,7.61a7.1712,7.1712,0,0,1,6.085-4.5752C8.915,3.0122,9.1768,3,9.4424,3A8.6981,8.6981,0,0,1,16,6.0083,8.6981,8.6981,0,0,1,22.5576,3c.2656,0,.5274.0122.7862.0352A7.1713,7.1713,0,0,1,29.43,7.61,7.6866,7.6866,0,0,1,28.124,15.5615Z" style="fill:#212123"/></svg> </div><%}%> <% if (blogposts[i].liked == true) {%> <div id='likeBtn' onclick="Like()" class="wrapperHearts active"> <svg xmlns="http://www.w3.org/2000/svg" id="Love"><path d="M28.124,15.5615,16.7549,28.6558a1,1,0,0,1-1.51,0L3.876,15.5615A7.6866,7.6866,0,0,1,2.57,7.61a7.1712,7.1712,0,0,1,6.085-4.5752C8.915,3.0122,9.1768,3,9.4424,3A8.6981,8.6981,0,0,1,16,6.0083,8.6981,8.6981,0,0,1,22.5576,3c.2656,0,.5274.0122.7862.0352A7.1713,7.1713,0,0,1,29.43,7.61,7.6866,7.6866,0,0,1,28.124,15.5615Z" style="fill:#212123"/></svg> </div><%}%> </form>
AJAX
let likeButton = document.querySelector('.wrapperHearts'); let frm = $('#like'); function Like(){ frm.submit()} frm.submit(function (e) { e.preventDefault(e); var formData = new FormData(this); $.ajax({ async: true, type: frm.attr('method'), url: frm.attr('action'), data: formData, processData: false, contentType: false, success: function (data) { console.log("success"); console.log(data) if (data.liked == false){ likeButton.classList.add('active') $("#likesNumber").text(data.likes +1 + ' ' + 'Likes') } else{ likeButton.classList.remove('active') $("#likesNumber").text(data.likes -1 + ' ' + 'Likes') } }, error: function(request, status, error) { console.log("error") } }); });
问题根源
- 重复ID冲突:所有表单和按钮都使用了相同的ID(
like、likeBtn),DOM中ID必须唯一,jQuery选择器只会匹配第一个元素。 - 全局选择器局限:
document.querySelector('.wrapperHearts')和$('#like')仅获取第一个匹配元素,导致所有操作都指向首个帖子的按钮和表单。 - 全局函数绑定错误:
Like()函数是全局的,调用时始终触发首个表单的提交。 - 点赞数选择器不精准:
$("#likesNumber")同样只会匹配第一个点赞数容器,无法对应当前操作的帖子。
修复方案
修改后的HTML
移除重复ID,用类名标识元素,并添加点赞数容器:
<form class='like-form' action="/postLike/<%=blogposts[i]._id%>?_method=PATCH" method="POST"> <% if (blogposts[i].liked == false) {%> <div class="wrapperHearts like-btn"> <svg xmlns="http://www.w3.org/2000/svg" class="Love-icon"><path d="M28.124,15.5615,16.7549,28.6558a1,1,0,0,1-1.51,0L3.876,15.5615A7.6866,7.6866,0,0,1,2.57,7.61a7.1712,7.1712,0,0,1,6.085-4.5752C8.915,3.0122,9.1768,3,9.4424,3A8.6981,8.6981,0,0,1,16,6.0083,8.6981,8.6981,0,0,1,22.5576,3c.2656,0,.5274.0122.7862.0352A7.1713,7.1713,0,0,1,29.43,7.61,7.6866,7.6866,0,0,1,28.124,15.5615Z" style="fill:#212123"/></svg> </div><%}%> <% if (blogposts[i].liked == true) {%> <div class="wrapperHearts like-btn active"> <svg xmlns="http://www.w3.org/2000/svg" class="Love-icon"><path d="M28.124,15.5615,16.7549,28.6558a1,1,0,0,1-1.51,0L3.876,15.5615A7.6866,7.6866,0,0,1,2.57,7.61a7.1712,7.1712,0,0,1,6.085-4.5752C8.915,3.0122,9.1768,3,9.4424,3A8.6981,8.6981,0,0,1,16,6.0083,8.6981,8.6981,0,0,1,22.5576,3c.2656,0,.5274.0122.7862.0352A7.1713,7.1713,0,0,1,29.43,7.61,7.6866,7.6866,0,0,1,28.124,15.5615Z" style="fill:#212123"/></svg> </div><%}%> <div class="likes-number"><%= blogposts[i].likes %> Likes</div> </form>
修改后的AJAX
使用事件委托绑定点击事件,通过相对DOM查找定位当前操作的元素:
// 事件委托绑定所有点赞按钮 $(document).on('click', '.like-btn', function() { const $btn = $(this); const $form = $btn.closest('.like-form'); const $likesNumber = $form.find('.likes-number'); $.ajax({ async: true, type: $form.attr('method'), url: $form.attr('action'), data: new FormData($form[0]), processData: false, contentType: false, success: function(data) { console.log("success"); console.log(data); // 更新按钮状态和点赞数 if (data.liked) { $btn.addClass('active'); } else { $btn.removeClass('active'); } $likesNumber.text(data.likes + ' Likes'); }, error: function(request, status, error) { console.log("error"); } }); });
核心修改说明
- 移除重复ID:所有元素改用类名,避免DOM唯一性冲突。
- 事件委托:确保动态生成的帖子按钮也能触发事件。
- 相对DOM查找:通过
closest()和find()精准定位当前按钮对应的表单和点赞数容器,不再操作全局第一个元素。 - 去掉全局函数:直接在点击事件中处理AJAX逻辑,避免全局绑定错误。
内容的提问来源于stack exchange,提问作者CristianMihai
相关产品推荐
相关产品推荐

