点击Alert确定按钮后如何阻止页面刷新?异步表单提交异常排查
我有一个更新用户资料的表单,想在密码字段为空时提醒用户。目前用户留空密码提交表单时,会弹出Alert提示,但点击确定后页面刷新,密码被设为空。
我的初始代码如下:
$userProfileForm.on("submit", handleUpdateUserProfile); async function handleUpdateUserProfile(e) { e.preventDefault(); const updatedUser = { name: $("#edit-user-name").val(), password: $("#edit-user-password").val(), }; if (!updatedUser.password) { alert("Password can't be empty!"); // 无效,页面仍会刷新并将密码设为空 return false; } else { currentUser = await currentUser.updateProfile(updatedUser); saveUserCredentialsInLocalStorage(); return true; } }
我也尝试了e.preventDefault(),但同样无效。请告诉我如何阻止页面重新加载。谢谢!
编辑:
我将return false改为return true后问题解决了……但控制台出现警告:[Violation] 'submit' handler took 1130ms jquery:5229
有人能帮我解释这是怎么回事吗?
新代码如下:
$userProfileForm.on("submit", handleUpdateUserProfile); async function handleUpdateUserProfile(e) { e.preventDefault(); const updatedUser = { name: $("#edit-user-name").val(), password: $("#edit-user-password").val(), }; if (!updatedUser.password) { alert("Password can't be empty!"); // 现在有效,页面不刷新但出现警告 return true; } else { currentUser = await currentUser.updateProfile(updatedUser); saveUserCredentialsInLocalStorage(); // 我必须使用reload()强制页面更新 location.reload(); } }
问题分析与解决方案
1. 初始代码中e.preventDefault()失效的原因
你的事件处理函数是async函数,这类函数默认返回一个Promise而非布尔值。jQuery处理异步事件处理器时,不会等待Promise完成,也无法将返回的Promise识别为false来阻止默认行为。因此即使你写了return false,这个值会被包装成resolved状态的Promise,jQuery无法据此拦截表单提交,页面仍会刷新。
2. 改return true后页面不刷新但出现性能警告的原因
改成return true后,返回的是resolved为true的Promise,但由于你已经调用了e.preventDefault(),jQuery不会触发默认的表单提交逻辑,页面因此不再刷新。而性能警告是因为alert()是同步阻塞式弹窗:弹窗弹出后,整个JS线程会暂停,直到用户点击确定按钮。如果用户停留弹窗的时间超过1秒,浏览器就会判定事件处理函数执行时间过长,抛出性能违规警告。
正确写法
无需依赖返回值,确保e.preventDefault()执行即可阻止默认提交,同时替换alert()为非阻塞的页面内提示,避免线程阻塞:
$userProfileForm.on("submit", handleUpdateUserProfile); async function handleUpdateUserProfile(e) { e.preventDefault(); // 直接阻止默认提交行为,无需依赖返回值 const updatedUser = { name: $("#edit-user-name").val(), password: $("#edit-user-password").val(), }; if (!updatedUser.password) { // 用页面内DOM提示替代alert,避免阻塞线程 $("#password-error").text("密码不能为空!").show(); return; } // 执行更新逻辑,增加错误捕获 try { currentUser = await currentUser.updateProfile(updatedUser); saveUserCredentialsInLocalStorage(); location.reload(); } catch (error) { console.error("用户资料更新失败:", error); $("#update-error").text("更新失败,请稍后重试").show(); } }
内容的提问来源于stack exchange,提问作者Jadeyyy

