以下代码blur从一个空的输入字段开始不断地产生alert.
为什么?
在哪些浏览器/操作系统中观察到这种行为?
操作系统:Ubuntu 14.04.5 LTS
浏览器:Google Chrome 55.0.2883.87(64 位)
let limit = 0; // Ограничиваем число алертов, этот limit не относится к вопросу
function valid(el) {
if (!el.value && limit++<3) {
alert('Value is empty');
el.focus();
} else limit = 0;
}
<input onblur="valid(this)">
附录:在另一次迭代
执行会打破恶性循环(尽管并非总是如此): el.focusevent loop
function valid(el) {
if (!el.value) {
alert('Value is empty');
setTimeout(() => el.focus());
}
}
问题源于这样一个事实,即在 Chrome 浏览器中,脚本在 UI 线程上运行,并且同一线程被模态窗口阻塞(模态窗口阻塞线程是操作系统或图形库的一个特性,而不是浏览器).
结果是这样的场景:
一般来说,无论浏览器如何, focus 和 blur 事件都永远不会“可信”——这就是它们的本质。仅仅是因为元素的焦点始终由用户控制,用户与浏览器交互的速度比脚本执行的速度快(例如,如果您使用输入自动化工具)。除了模式窗口之外,Punto Switcher、密码存储或一些为残障人士提供的工具也可能会破坏您的脚本。
focus 和 blur 事件总是有点晚,
el === document.activeElement即使在普通浏览器中,额外的检查似乎也不错:PS 一般来说,不释放输入焦点和垃圾邮件警报本身就是一个糟糕的主意,没有任何错误。
最好在填写的表单旁边显示验证错误,禁止提交无效表单。
这是一个已知的 Chromium 错误:#666205(感谢@Grundy)
2 月 27 日,此错误已关闭,标签为Won't Fix:
另一方面,@SLy_huh建议的解决方法非常有效: