替换输入元素只会在 Chrome 中导致 onchange 事件

Replacing an input element causes onchange event in Chrome only

本文关键字:onchange 事件 Chrome 输入 元素 替换      更新时间:2023-09-26

我发现Chrome和Firefox之间的行为存在奇怪的差异,我想知道是否有人知道发生了什么。

首先,代码(有关实时示例,请参见 http://jsfiddle.net/pXgaE/1/):

.HTML:

<input id='me' onchange='func()' />

Javascript:

function func() {
    console.log( "resetting" );
    document.getElementById( 'me' ).parentNode.innerHTML = "test";
}

Firefox 中,如果我在字段中键入内容并按"输入",日志消息会出现一次。另一方面,在Chrome中,日志消息出现两次

Chrome的事件处理有什么不同(错误?)?

旁白:不,我也不太喜欢这段代码,我更愿意更明智地重写它。但我真的很好奇,引擎盖下发生了什么可以解释这一点。

编辑:出于某种原因,每次关闭输入标签都会得到我。它们现在应该适当关闭。另外,仅供参考,我在Mac上的Chrome 30.0.1599.101以及Chrome Canary 32.0.1680.0上都出现了这种行为。

编辑2:我最初将innerHTML设置为另一个输入标签,但是我可以通过设置为纯文本来重现它。更新 Javascript 和 JSFiddle 链接。

通过@carter和第二个测试用例的一些见解,我想我明白现在发生了什么。

首先,onchange事件针对正常的输入新文本和点击输入情况触发。这在Firefox和Chrome中都会发生,这是我所期望的。

其次,在 Chrome 中,如果input"脏"(即有更改)并随后被销毁,则 onchange 事件也会触发。这在 Firefox 中不会发生。请注意,脏input很重要 - 如果自上次onchange以来没有发生任何更改,则通常不会发送另一个事件。

不过,Chrome 对这种行为有一个例外:如果input在处理onchange事件期间被破坏,它显然仍然认为input是脏的,因此会触发第二个onchange事件。

您可以通过将上面的 Javascript 更改为以下内容来查看这一点:

function func() {
    console.log( 'resetting' );
}
setTimeout( function() {
    document.getElementById( 'me' ).parentNode.innerHTML = 'test';
}, 3000 );

你会看到,如果你在替换发生之前输入输入,你会在Chrome中收到日志消息,但在Firefox中不会。