如何检测DOM元素上reportValidity()是否正在显示validityMessage?
解决Safari中重复调用
reportValidity()导致验证消息切换的问题 核心问题
在Safari中,重复调用reportValidity()会切换验证消息的显示/隐藏状态,而Firefox无此行为。当提交无效表单时,form.reportValidity()会自动聚焦到第一个无效输入框,触发输入框的focus事件;若此时focus事件中也调用了input.reportValidity(),就会在Safari中导致刚显示的验证消息被隐藏。
浏览器目前没有提供公开接口直接检测验证消息的显示状态,因此需要通过控制reportValidity()的调用时机来规避跨浏览器差异。
解决方案
通过临时标志区分「表单提交导致的聚焦」和「用户手动触发的聚焦」,避免在提交流程中重复调用reportValidity():
修改后的代码示例
HTML
<form action="#" id="form"> <input type="number" max="5" value="10" name="invalid" id="invalid" autocomplete="off"> <input type="submit" value="validate"> </form>
JavaScript
const input = document.getElementById("invalid"); const form = document.getElementById("form"); // 标记是否为表单提交导致的聚焦 let isSubmitting = false; input.addEventListener("focus", () => { // 仅当非提交触发的聚焦、且输入框确实无效时,才显示验证消息 if (!isSubmitting && !input.checkValidity()) { input.reportValidity(); } }); form.addEventListener("submit", (e) => { e.preventDefault(); isSubmitting = true; form.reportValidity(); // 延迟清除标志,确保浏览器完成聚焦后不影响后续手动操作 setTimeout(() => { isSubmitting = false; }, 100); });
原理说明
- 表单提交时先设置
isSubmitting为true,再触发表单验证; - 浏览器自动聚焦到无效输入框时,
focus事件因检测到isSubmitting为true,跳过reportValidity()调用,避免Safari中消息被隐藏; - 用
setTimeout延迟清除标志,确保用户后续手动聚焦输入框时,依然能正常触发验证消息; - 加入
input.checkValidity()判断,确保只有输入框确实无效时才调用验证方法,避免无意义的执行。
内容的提问来源于stack exchange,提问作者martinemde
相关产品推荐
相关产品推荐

