当改变来自另一个函数时,onchange事件不触发。

19

我有一个输入文本框,它的值来自一个JavaScript函数(倒计时计时器)。

当输入文本框的值为0时,我想触发一个事件,所以我使用了change事件监听器。

不幸的是,当更改来自JavaScript函数时,它似乎无法触发该事件。

如何强制使change事件起作用,即使更改来自JavaScript而不是用户?

6个回答

22

来自精细的手册

change
当一个控件失去输入焦点且其值在获得焦点后被修改时,触发change事件。此事件适用于INPUT、SELECT和TEXTAREA元素。

当您通过代码修改文本输入的值时,不会触发change事件,因为没有焦点变化。但是,您可以使用createEventdispatchEvent手动触发该事件,例如:

el = document.getElementById('x');
ev = document.createEvent('Event');
ev.initEvent('change', true, false);
el.dispatchEvent(ev);

这里还有一个实时版本:http://jsfiddle.net/ambiguous/nH8CH/


2
如果您使用任何现代事件监听方法,这将无法工作;它只能在使用旧的 onchange 属性时起作用。您应该使用DOM事件API来触发事件。 - Delan Azabani
@Delan:你能看出我已经很久没写原生JavaScript了吗?我会修补它的。 - mu is too short

4

3
在修改数值的函数中,手动触发一个change事件。
var e = document.createEvent('HTMLEvents');
e.initEvent('change', false, false);
some_input_element.dispatchEvent(e);

需要使用 HTMLEvents 吗?jQuery版本显然使用 Event,我能看到唯一的区别是DOM级别2与级别3。 - mu is too short
据我所知,HTMLEventsEventEvents 是同义词。 - Delan Azabani
“Event” 似乎是官方的标准,而“Events” 可能会在一些浏览器中出现以匹配“hasFeature”的复数形式。 - mu is too short

1
一种更可重复使用的选项:
function simulate_event(eventName, element) {
    // You could set this into the prototype as a method.
    var event;

    if (document.createEvent) {
        event = document.createEvent("HTMLEvents");
        event.initEvent(eventName, true, true);
    } else {
        event = document.createEventObject();
        event.eventType = eventName;
    };

    event.eventName = eventName;

    if (document.createEvent) {
        element.dispatchEvent(event);
    } else {
        element.fireEvent("on" + event.eventName, event);
    }
};

1

只需在getter和setter中重新定义节点的"value"属性,使用getAttribute("value")setAttribute("value", newValue),并在setter末尾分派"change"事件即可。例如:

myNode.onchange = e => console.log("Changed!", e.target.value);

Object.defineProperty(myNode, "value", {
  get: () => myNode.getAttribute("value"),
  set(newValue) {
    myNode.setAttribute("value", newValue);
    myNode.dispatchEvent(new Event("change")); //or define the event earlier, not sure how much of a performance difference it makes though
  }
})

var i = 0;
setTimeout(function changeIt() {
    if(i++ < 10) {
        myNode.value = i;
        setTimeout(changeIt, 1000);
    }
}, 1)
<input id="myNode">


0

你可以使用 keypress 事件来替代 change 事件。

这是因为 change 事件只有在输入框失去焦点时才会触发,而不是在每次按键时触发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接