当keydown事件(TAB键)修改元素值时,不会触发更改事件

Bil*_*oga 6 javascript jquery

鉴于以下HTML:

<input type="text" id="test" />
Run Code Online (Sandbox Code Playgroud)

和JavaScript:

var $test = $('#test');

$test.on('keydown', function(event) {
    if (event.keyCode === 9) {
        $(event.target).val('change it!');
    }
});

$test.on('change', function(event) {
    alert('I am not called!');
});
Run Code Online (Sandbox Code Playgroud)

如果我在输入中键入任何内容并点击tab,为什么change事件不会触发?该keydown事件将触发,并更新输入的值.

如果我删除了.val()电话,那就change开火了.

起初,我认为这是一个jQuery问题(运行1.9.1),但确认如果我使用纯JavaScript,会发生相同的行为.

mjk*_*mjk 7

change仅触发用户提交的更改.换句话说,使用JavaScript来更改背景中元素的值不会触发change.

Tab实际上并没有改变元素的内容; 它只是切换焦点.在某些方面,你输入标签来改变元素的内容是巧合的(你也可以按一个按钮间接更新它,这也不会触发change).

DOM规范解释了为什么在您的特定情况下,如果您键入和制表符,则会丢弃用户输入并且不会触发任何更改.

特别:

对于任何给定的键,本规范中定义的键盘事件以相对于彼此的设定顺序发生:

  • KEYDOWN
  • keypress(仅适用于产生字符值的键)
  • 与此密钥相关的任何默认操作
  • KEYUP

当您按Tab键时,会keydown被触发.Boom,你的事件处理程序被调用!元素内容由您的脚本更新 - 没有因为脚本正在执行此操作而触发更改.用户贡献的内容被删除.现在是时候浏览器执行与tab关联的默认操作了:将焦点移开并查看元素是否被用户更改(触发onchange).不,它被剧本改变了!不要change开枪.

因此,如果你删除该val()行,你会发现两件事.

  1. 如果您将元素焦点和制表符关闭,则不会change触发 - 未发生任何更改,因为制表符不会更改字段内容.
  2. 如果你给元素焦点并输入一些东西并选项卡关闭,change则会触发,因为在那个神奇的"与标签相关的默认操作"时刻,浏览器会注意到用户做出了更改.

呼!