也许这是我的一个误解,但我认为,当您创建自定义事件,然后创建"具有事件侦听器的元素"(侦听该事件)时,事件(本身)会跟踪等待事件发生的所有侦听器,并且当事件发生时,所有侦听器都会自动收到通知。
然而,在我看到的所有例子中,通知过程看起来是非常明确的(不是非常自动的);您必须通过以下方式手动编写将事件分派给每个侦听元素的代码:
elementName.dispatchEvent(eventName);
例如,我刚刚将测试代码编写为:
- 创建基本自定义事件
- 为自定义事件 生成100个div元素和监听器
- 使每个div的背景色在事件发生时变为红色发生
var myEvent = new CustomEvent("redTime", {});
var div;
for(var i=1, iL=101; i < iL; i++)
{
div = document.createElement('div');
document.body.appendChild(div);
div.innerHTML = i;
div.style.border = "solid 1px #333333";
div.style.display = "inline-block";
div.style.margin = "1px";
div.style.padding = "1px";
div.addEventListener("redTime", function(e)
{
this.style.backgroundColor = "red";
});
document.body.appendChild(div);
}
div.dispatchEvent(myEvent);
显然,我希望上面的最后一行代码只使最后一个div的背景颜色为红色,但是我不知道有一个方法(不创建循环)可以分派给所有侦听器。
然而,在尝试这个实验之前,我假设事件对象的某些方法将把事件分派给所有订阅的侦听器(并使所有div为红色)。我认为这就是addEventListener方法的主要目的:创建某种类型的"幕后列表",其中包含在事件发生时要通知的所有元素。
您真的必须手动分派到每个正在侦听的元素吗?
将自定义事件分派给特定目标对象的侦听器。它不会被分派给该事件的所有监听器,无论该事件被分派给哪个对象或哪个对象正在被监听?它的工作原理与"点击"事件的工作原理完全相同。事件只分配给特定对象,并且只有该事件的侦听器附加到该特定对象。
如果你想要一个全局事件和全局监听器,那么你可以创建一个已知对象,让每个人都监听该对象上的事件,然后将事件分派给该对象。然后,每个人都会收到事件的通知。
你可能会发现像这样使用eventEmitter对象会更容易。
但是,如果你想做的是改变一堆div
对象的一些属性,那么我建议你只是把一个共同的类名放在它们上,并使用document.querySelectorAll()
来检索所有的目标元素,然后在它们上运行一些代码。我不认为自定义事件监听器有什么特别的原因,因为它们并没有真正做你正在做的事情。
你可以这样写:
function iterateTargets(selector, fn, data) {
var items = document.querySelectorAll(selector);
for (var i = 0; i < items.length; i++) {
fn(items[i], data);
}
}
iterateTargets(".specials", function(item){
item.style.backgroundColor = "red;
});
或者在没有回调函数的情况下工作于样式设置的版本:
function iterateTargets(selector, fn, data) {
var items = document.querySelectorAll(selector);
for (var i = 0; i < items.length; i++) {
fn(items[i], data);
}
}
function setStyles(selector, styleName, value) {
iterateTargets(selector, function(item) {
item.style[styleName] = value;
});
}
setStyles(".specials", "backgroundColor", "red");