focus()方法和事件顺序(在纯JavaScript中)

时间:2016-02-13 09:14:05

标签: javascript events asynchronous focus synchronous

我目前正在开发一个具有复杂帮助系统的大型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规范,因为在很多情况下事件顺序和调用事件处理程序的顺序是错误的。但我一直非常肯定(到现在为止)至少指定为阻塞的方法确实以同步方式调用...

0 个答案:

没有答案