Web表单Blur事件触发无限循环:如何实现校验后聚焦不重复触发?
解决Web表单blur事件无限循环的问题
这个无限循环的核心原因是:alert弹窗会抢占页面焦点,当你关闭弹窗后执行focus(),浏览器会先把焦点从当前元素移开(再次触发blur事件),再把焦点移回目标控件,导致校验逻辑反复触发,形成死循环。
同时注意原代码有个语法错误:if $("#selGender :selected").val() === "F")缺少开头的括号,正确写法是if ($("#selGender :selected").val() === "F"),不修正的话代码会直接报错。
下面是两种简单可行的解决方案:
方案一:用标志变量跳过不必要的blur触发
添加一个临时变量,用来标记是否需要跳过本次blur事件的校验逻辑:
let skipBlur = false; $('#selPregnant').on('blur', function() { // 如果是主动触发focus导致的blur,直接跳过校验 if (skipBlur) { skipBlur = false; return; } if ($("#selGender :selected").val() === "F") { if ($("#selPregnant").val() === '') { alert('If the individual is female, the pregnancy question MUST be answered.'); // 标记下一次blur需要跳过 skipBlur = true; $('#selPregnant').focus(); } } });
方案二:用setTimeout延迟执行focus操作
利用setTimeout把focus操作放到浏览器事件队列的末尾,等alert关闭后的焦点处理流程完成后再执行:
$('#selPregnant').on('blur', function() { if ($("#selGender :selected").val() === "F") { if ($("#selPregnant").val() === '') { alert('If the individual is female, the pregnancy question MUST be answered.'); // 延迟执行focus,避免触发额外blur setTimeout(() => { $('#selPregnant').focus(); }, 0); } } });
两种方案都能有效避免无限循环,其中标志变量的方法逻辑更清晰,setTimeout的方法代码更简洁,根据自己的需求选择即可。
内容的提问来源于stack exchange,提问作者Bob Stout
相关产品推荐
相关产品推荐

