原文出处:http://www.cnblogs.com/silin6...
整 理:https://segmentfault.com/write

1.问题来源

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>setTimeout</title>
    <script type="text/javascript">
        function get(id) {
            return document.getElementById(id);
        }
        window.onload = function () {
            //第一个例子:未使用setTimeout
            get('makeinput').onmousedown = function () {
                var input = document.createElement('input');
                input.setAttribute('type', 'text');
                input.setAttribute('value', 'test1');
                get('inpwrapper').appendChild(input);
                input.focus();
                input.select();
            }
            //第二个例子:使用setTimeout
            get('makeinput2').onmousedown = function () {
                var input = document.createElement('input');
                input.setAttribute('type', 'text');
                input.setAttribute('value', 'test1');
                get('inpwrapper2').appendChild(input);
                //setTimeout
                setTimeout(function () {
                    input.focus();
                    input.select();
                }, 0);
            }
            //第三个例子,onkeypress输入的时候少了一个值
            get('input').onkeypress = function () {
                get('preview').innerHTML = this.value;
            }
        }
    </script>
</head>
<body>
    <h1><code>setTimeout</code></h1>
    <h2>1、未使用 <code>setTimeout</code></h2>
    <button id="makeinput">生成 input</button>
    <p id="inpwrapper"></p>


    <h2>2、使用 <code>setTimeout</code></h2>
    <button id="makeinput2">生成 input</button>
    <p id="inpwrapper2"></p>


    <h2>3、另一个例子</h2>
    <p>
        <input type="text" id="input" value="" /><span id="preview"></span>
    </p>
</body>
</html>

代码运行实例请戳:http://runjs.cn/detail/uf2rofq7
通过代码运行实例我们发现:

图片描述

实例1中的文本框并没有聚焦,文本内容也没有被选中
实例2中的文本框聚焦,并且文本内容被选中
实例3中,在文本框中输入内容,显示的总会比输入的慢一拍

2.问题讲解

下面用两张图来说明问题:

注意:这里值得思考的focus()的执行时机,根据这次测试观察,发现focus事件好像挂载在mousedown之内的最后面,而不是直接挂在mousedown的后面。它和mousedown仿佛是一体的。

实例1执行流程图:
图片描述

我们使用setTimeout之前的任务流程是这样的(->表示在上一个任务中,=>表示在上一个任务后):
onmousedown -> onmousedown中执行了input.focus() -> button.onfocus => onmouseup => onclick

实例2执行流程图:
而我们使用了setTimeout之后的任务流程是这样的:
onmousedown -> button.onfocus => input.focus => onmouseup => onclick
图片描述

而从上面的流程上我们得知了另外的消息,我们还可以把input.focus挂在mouseup和click下,因为在这些事件之前,我们的按钮已经得到过焦点了,不会再抢我们的焦点了。


specialcoder
2.2k 声望170 粉丝

前端 设计 摄影 文学