【发布时间】:2011-10-26 17:03:46
【问题描述】:
我有一个从 Javascript 函数(带倒计时的计时器)获取他的值的输入文本。
我想在输入文本为 0 时引发一个事件,所以我使用了 change eventListener。
不幸的是,当更改来自 javascript 函数时,它似乎没有引发事件。
即使更改来自 Javascript 而不是来自用户,我如何才能强制更改事件起作用?
【问题讨论】:
标签: javascript dom-events
我有一个从 Javascript 函数(带倒计时的计时器)获取他的值的输入文本。
我想在输入文本为 0 时引发一个事件,所以我使用了 change eventListener。
不幸的是,当更改来自 javascript 函数时,它似乎没有引发事件。
即使更改来自 Javascript 而不是来自用户,我如何才能强制更改事件起作用?
【问题讨论】:
标签: javascript dom-events
来自fine manual:
改变
当控件失去输入焦点并且其值在获得焦点后已被修改时,会发生更改事件。此事件对 INPUT、SELECT 和 TEXTAREA 有效。元素。
当您通过代码修改文本输入的值时,不会触发更改事件,因为没有焦点更改。您可以使用createEvent 和dispatchEvent 自己触发事件,例如:
el = document.getElementById('x');
ev = document.createEvent('Event');
ev.initEvent('change', true, false);
el.dispatchEvent(ev);
【讨论】:
onchange 属性时,它才会起作用。您应该使用 DOM 事件 API 来触发事件。
在更改值的函数中,手动触发change 事件。
var e = document.createEvent('HTMLEvents');
e.initEvent('change', false, false);
some_input_element.dispatchEvent(e);
【讨论】:
HTMLEvents吗? jQuery 版本显然使用了Event,我能看到的唯一区别是 DOM 级别 2 与级别 3。
HTMLEvents、Event 和 Events 是同义词。
Event 似乎是官方的,Events 可能在某些浏览器中出现以匹配hasFeature 的复数形式。
现在是 2018 年,似乎不推荐使用 initEvent(): https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
我认为您现在可以单线触发事件: element.dispatchEvent(new Event('change'));
【讨论】:
一个更可重用的选项:
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);
}
};
【讨论】:
只需在 getter 和 setter 中使用 getAttribute("value") 和 setAttribute("value", newValue) 重新定义节点的“value”属性,并在 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">
【讨论】:
您可以使用keypress 事件来代替change。
这是因为 change 事件在不再聚焦之前不会触发 - 当您点击输入标签时。
【讨论】: