发起POST请求时event.preventDefault()失效,页面仍刷新如何解决?
问题描述
我尝试提交表单向json-server发送POST请求并在页面展示数据,为避免每次提交时页面刷新,在submit事件的第一行添加了event.preventDefault()。POST请求成功,表单数据已成功存入json-server,但提交时页面始终会刷新。我确定问题与POST请求有关,因为注释掉POST请求、添加console.log("form submitted")后提交表单,页面不会刷新且控制台能看到对应消息,但恢复POST请求后页面又会刷新。
相关代码片段
function monsterSubmit() { const monsterForm = document.getElementById("monster-form"); monsterForm.addEventListener("submit", event => { event.preventDefault(); const monsterObj = { name: event.target[0].value, age: event.target[1].value, description: event.target[2].value } fetch("http://localhost:3000/monsters", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify(monsterObj) }) .then(res => res.json()) .then(monster => console.log(monster)) .catch(err => console.log(err)) }) }
完整JS文件代码
document.addEventListener("DOMContentLoaded", () => { getMonsters(); monsterSubmit(); }) function getMonsters() { const monsterContainer = document.getElementById("monster-container"); fetch("http://localhost:3000/monsters?_limit=50") .then(res => res.json()) .then(monsters => { monsters.forEach(monster => { const monsterName = document.createElement("h2"); const monsterAge = document.createElement("h4"); const monsterBio = document.createElement("p"); const monsterInfo = document.createElement("div"); monsterName.textContent = monster.name; monsterAge.textContent = `Age: ${monster.age}`; monsterBio.textContent = `Bio: ${monster.description}`; monsterInfo.append(monsterName, monsterAge, monsterBio); monsterContainer.appendChild(monsterInfo); }) }) .catch(err => console.error(err)) } function monsterSubmit() { const monsterForm = document.getElementById("monster-form"); monsterForm.addEventListener("submit", event => { event.preventDefault(); const monsterObj = { name: event.target[0].value, age: event.target[1].value, description: event.target[2].value } fetch("http://localhost:3000/monsters", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify(monsterObj) }) .then(res => res.json()) .then(monster => console.log(monster)) .catch(err => console.log(err)) }) }
解决方案
1. 检查HTML表单属性
确认表单标签没有设置action属性,也没有通过onsubmit绑定其他提交逻辑——如果存在这些属性,可能会绕过event.preventDefault()触发默认提交刷新。
2. 补充阻止事件冒泡
在event.preventDefault()后添加event.stopPropagation(),防止事件冒泡引发的意外默认行为:
monsterForm.addEventListener("submit", event => { event.preventDefault(); event.stopPropagation(); // 新增这一行 // 剩余代码不变 })
3. 排查响应解析错误
虽然POST请求成功,但如果json-server返回的响应不是合法JSON,res.json()会抛出异常,可能导致浏览器出现意外行为。可以临时修改fetch的响应处理逻辑,排查问题:
fetch("http://localhost:3000/monsters", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify(monsterObj) }) .then(res => { console.log("响应状态码:", res.status); return res.text(); // 先获取文本而非直接解析JSON }) .then(text => { console.log("响应内容:", text); try { const monster = JSON.parse(text); console.log("解析后的怪物数据:", monster); } catch (err) { console.error("JSON解析失败:", err); } }) .catch(err => console.error("请求错误:", err))
4. 确保事件只绑定一次
在monsterSubmit函数开头添加日志,确认该函数只执行一次(避免重复绑定submit事件导致冲突):
function monsterSubmit() { console.log("绑定submit事件"); // 新增日志 const monsterForm = document.getElementById("monster-form"); // 剩余代码不变 }
如果控制台多次打印这句话,说明函数被重复调用,需要排查调用时机。
额外优化建议
不要通过索引event.target[0]获取表单元素,给表单控件添加name属性后通过名称取值,代码更稳定:
<!-- HTML表单示例 --> <form id="monster-form"> <input type="text" name="name" placeholder="怪物名称"> <input type="number" name="age" placeholder="年龄"> <textarea name="description" placeholder="描述"></textarea> <button type="submit">添加怪物</button> </form>
// JS中取值 const monsterObj = { name: event.target.name.value, age: event.target.age.value, description: event.target.description.value }
内容的提问来源于stack exchange,提问作者Christian Lopez
相关产品推荐
相关产品推荐

