Flask+JS无刷新投票按钮失效:跳转至JSON页面问题求助
问题原因&修复方案
核心问题拆解
仅单个表单绑定了阻止默认提交的事件
第二个评论投票表单没有vote_formID,JS仅给帖子投票表单添加了阻止提交逻辑,点击评论投票时浏览器直接触发默认表单提交,跳转到后端返回JSON的页面。Fetch请求未携带表单数据
代码创建了FormData但未在请求中作为body传递,后端无法获取submit参数,即便事件绑定正确,投票逻辑也无法正常执行。DOM元素操作错误
querySelectorAll返回的是元素集合,直接修改formBtn的innerHTML和className无效,需定位到触发提交的具体按钮。投票状态判断逻辑错误
用data["votes"] === true判断投票状态,但后端返回的voted才是布尔值,votes是投票数(数字),导致样式无法正确切换。Async/await与.then混用导致响应处理混乱
同时使用两种异步处理方式会让响应解析逻辑混乱,后续console.log(await response.json())会重复解析已消费的响应体,触发错误。
具体修复步骤
1. 修改HTML:给表单和按钮添加统一类名
给两个表单加上vote-form类,按钮加上vote-btn类,方便批量绑定事件和定位元素:
<form class="d-inline vote-form" action="{{ url_for('main.post', id=post.id) }}" method="post"> <input name="csrf_token" type="hidden" value="{{ csrf_token }}"> <button class="px-1 py-0 btn btn-outline-dark btn-sm vote-btn" type="submit" name="submit" value="vote_post">⇧ 2</button> </form> <form class="d-inline vote-form" action="{{ url_for('main.post', id=comment.id) }}" method="post"> <input name="csrf_token" type="hidden" value="{{ csrf_token }}"> <button class="px-1 py-0 btn btn-outline-dark btn-sm vote-btn" type="submit" name="submit" value="vote_comment">⇧ 0</button> </form>
2. 重写JS:修复事件绑定与逻辑错误
给所有投票表单批量绑定事件,修正数据传递和DOM操作逻辑:
// 给所有带vote-form类的表单绑定提交事件 document.querySelectorAll('.vote-form').forEach(form => { form.addEventListener('submit', async (event) => { // 阻止默认提交,避免页面跳转 event.preventDefault(); // 获取当前触发提交的投票按钮 const currentBtn = event.target.querySelector('.vote-btn'); // 组装表单数据(自动包含csrf_token和submit参数) const formData = new FormData(form); const url = form.getAttribute('action'); try { // 发送POST请求并携带表单数据 const response = await fetch(url, { method: 'POST', body: formData }); if (!response.ok) throw new Error('投票请求失败'); // 解析后端返回的JSON数据 const data = await response.json(); // 更新按钮的投票数(保留箭头,替换数字) currentBtn.innerHTML = `⇧ ${data.votes}`; // 根据voted状态切换按钮样式 if (data.voted) { currentBtn.className = 'px-1 py-0 btn btn-secondary btn-sm vote-btn'; } else { currentBtn.className = 'px-1 py-0 btn btn-outline-dark btn-sm vote-btn'; } } catch (err) { console.error('投票出错:', err); } }); });
3. 后端可选优化(减少重复查询)
投票后直接刷新当前对象,无需重新从数据库查询:
# 以帖子投票逻辑为例,提交后刷新post对象 db.session.add(vote) db.session.commit() db.session.refresh(post) # 从数据库同步最新数据 return jsonify({"votes": post.votes_count(), "voted": True})
内容的提问来源于stack exchange,提问作者user23430396
相关产品推荐
相关产品推荐

