我目前正在开发一个具有复杂帮助系统的大型Web项目,因此需要深入了解何时同步或异步触发事件。
实际上,我正在使用我在很多地方使用的focus()方法,而且似乎没有像所有地方都记录的那样工作。我已阅读(某些部分)W3C DOM规范和许多文章和教程,所有这些都说明了相同的内容。当我们调用element.focus()时,应该发生以下情况:
1)光标(插入符号)设置为相应的元素。
2)处理相应元素的焦点事件的所有事件处理程序以同步(阻塞)方式调用,即保证在elem.focus()返回之前调用所有这些处理程序。换句话说,在 elem.focus()返回后,可以保证这些处理程序的 none 将被称为。
在开发我的应用程序时,我依赖于这种行为,但现在看来(至少)IE11和Chrome不遵守这些规则。如果有人能按照以下步骤回答我的最后一个问题,我想我能理解发生了什么。
首先,请考虑以下HTML文档:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<title>Test</title>
</head>
<body>
<input type="button" value="click me" />
<input type="text" />
<script>
function ButtonHandler(e) {
alert('in onclick')
text.focus()
alert('out onclick')
}
function FieldHandler(e) {
alert('onfocus')
text.onfocus = null
}
var button = document.body.children[0]
var text = document.body.children[1]
button.onclick = ButtonHandler
text.onfocus = FieldHandler
</script>
</body>
</html>
我从这里获得了部分代码:http://javascript.info/tutorial/events-and-timing-depth。作者使用该代码来证明elem.focus()确实同步工作。为了简单起见,让我们使用IE11来显示我的问题。
请将如上所示的HTML文档加载到IE11中。然后单击页面白色区域的任意位置以获得文本输入的焦点,然后点击重新加载。您现在应该有一个新加载的文档,文本输入没有聚焦。
现在,当您单击该按钮时,您将收到三个警报:onclick,onfocus,out onclick(按此顺序)。这似乎证明了elem.focus()的行为是同步的。
现在考虑以下HTML文档:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<title>Test</title>
</head>
<body>
<input type="button" value="click me" />
<input type="text" />
<script>
function ButtonHandler(e) {
console.log('in onclick')
text.focus()
console.log('out onclick')
}
function FieldHandler(e) {
console.log('onfocus')
text.onfocus = null
}
var button = document.body.children[0]
var text = document.body.children[1]
button.onclick = ButtonHandler
text.onfocus = FieldHandler
</script>
</body>
</html>
它与第一个文档完全相同,但有以下例外:我已通过console.log()替换了alert()。
现在,请将该文档加载到IE11并打开IE11的控制台。再次,将焦点从文本输入中移开并重新加载文档,然后单击按钮。控制台现在显示以下行(按此顺序):
in onclick out onclick onfocus
这似乎证明了对elem.focus()的调用是异步完成(在 elem.focus()返回后,焦点处理程序显然被称为),这对我的申请来说是一个很大的问题。
可以请任何人向我解释为什么elem.focus()似乎在第一个文档中是同步的,但在第二个文档中是异步的?
顺便说一句,我在这里使用的是IE11,因为我已经能够找到上面的例子,这很容易理解。我希望有人会对我的问题给出一般性答案,并且我不会被告知这只是IE11的错误行为。
Firefox似乎是唯一能够做到正确的浏览器,即使使用第一个文档,Chrome也会失败。我已经知道浏览器不遵守DOM规范,因为在很多情况下事件顺序和调用事件处理程序的顺序是错误的。但我一直非常肯定(到现在为止)至少指定为阻塞的方法确实以同步方式调用...