javascript - 具有不同触发元素和监听器元素的自定义事件

标签 javascript dom-events

var event = new CustomEvent("custom-event", {bubbles:true, detail:"something"});
var eleA = document.getElementById("A");
var eleB = document.getElementById("B");
eleB.addEventListener("custom-event", function(e) {
    console.log("custom-event caught in element B", e.detail);
});
document.addEventListener("custom-event", function(e) {
    console.log("custom-event caught in document", e.detail);
});
eleA.dispatchEvent(event);
<html>
<body>
<div id="A">A</div>
<div id="B">B</div>
</body>
</html>

我搜索了过去的问题,但找不到答案。我有一个元素 A 触发自定义事件,并希望另一个元素 B 接收该事件并对其采取行动。例如:

var event = new CustomEvent("new-event");
var eleA = document.querySelector("#A");
eleA.dispatchEvent(event);

//...
// somewhere else
...
var eleB = document.querySelector("#B");
eleB.addEventListener("new-event", function(e) {
   console.log('heard');
});

我发现该事件没有被触发。我尝试添加:

var event = new CustomEvent("new-event", {bubbles:true});

但没有区别,但是,如果我将监听器更改为如下所示,它就可以工作:

document.addEventListener("new-event", function(e) {
   console.log('heard in document');
});

是因为传播问题吗?有没有一种方法可以让我只在一个或多个特定元素中收听它?

最佳答案

您混淆了 dispatchEvent 函数的使用。

.dispatchEvent()

Dispatches an Event at the specified EventTarget, invoking the affected EventListeners in the appropriate order. The normal event processing rules (including the capturing and optional bubbling phase) also apply to events dispatched manually with dispatchEvent().


A custom event is dispatched to the listeners of a specific target object. It is not dispatched to all listeners of that event no matter which object the event is dispatched to or which object is being listened to? It basically works exactly like a 'click' event works. The event is dispatched only to a specific object and only the listeners for that event attached to that specific object. Reference

事件将使用元素的上下文进行调度,并且监听该特定事件的每个元素都将收到通知。所以,您没有附加

将通过 addEventListener() 函数中使用的回调接收通知。

此代码片段显示 elementA、elementB 和 document 如何监听同一 new-event 事件:

var event = new CustomEvent("new-event");
var eleA = document.querySelector("#A");

eleA.addEventListener("new-event", function(e) {
  console.log('new-event from Element A');
});

eleA.dispatchEvent(event);

var eleB = document.querySelector("#B");
eleB.addEventListener("new-event", function(e) {
  console.log('new-event from Element B');
});

eleB.dispatchEvent(event);

document.addEventListener("new-event", function(e) {
  console.log('heard in document');
});

document.dispatchEvent(event);
<span id='A'></span>
<span id='B'></span>

此代码片段显示了元素如何监听自己的事件:

var event = new CustomEvent("new-event");
var eleA = document.querySelector("#A");

eleA.addEventListener("new-event", function(e) {
  console.log('new-event from Element A');
});

var eventB = new CustomEvent("new-eventB");
var eleB = document.querySelector("#B");
eleB.addEventListener("new-eventB", function(e) {
  console.log('new-event from Element B');
});

var eventDoc = new CustomEvent("new-eventDoc");
document.addEventListener("new-eventDoc", function(e) {
  console.log('heard in document');
});

eleA.dispatchEvent(event);
eleB.dispatchEvent(eventB);
document.dispatchEvent(eventDoc);
<span id='A'></span>
<span id='B'></span>

您可以创建一个 SharedResource 对象来向特定接收者通知事件。

此代码片段向您展示了如何操作:

  • eleA 通知 eleBdocument
  • eleC 通知eleB

//This Object represents a shared result among receivers.
var SharedResource = function(event) {
  this.event = event;
  this.receivers = [];

  this.addReceiver = function(receiver) {
    this.receivers.push(receiver);
  }

  this.addReceivers = function(receivers) {
    this.receivers.push.apply(this.receivers, receivers);
  }

  //This function will loop over receivers array to call the current event.
  this.notify = function() {
    var $self = this;
    this.receivers.forEach(function(receiver) {
      receiver.dispatchEvent(new CustomEvent($self.event));
    });
  }
};

//Element A will send a "broadcast" message to eleB and Document.
var eleA = document.querySelector("#A");
eleA.addEventListener("click", function(e) {
  ABDocSharedResource.notify();
});

var eleB = document.querySelector("#B");
eleB.addEventListener("new-event", function(e) {
  console.log('new-event from Element B');
});

document.addEventListener("new-event", function(e) {
  console.log('new-event from Document');
});

var ABDocSharedResource = new SharedResource('new-event');
ABDocSharedResource.addReceivers([eleB, document]);

//Element C will send a "broadcast" message to eleB.
var CBSharedResource = new SharedResource('new-event');
CBSharedResource.addReceiver(eleB);

var eleC = document.querySelector("#C");
eleC.addEventListener("click", function(e) {
  CBSharedResource.notify();
});
<a href="#" id='A'>Click me! (A) - Broadcast to B and Document</a>
<br>
<a href="#" id='C'>Click me! (C) - Broadcast to B</a>


<span id='B'></span>

关于javascript - 具有不同触发元素和监听器元素的自定义事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48539768/

相关文章:

javascript - 如何仅在滚动停止后经过特定时间时才触发事件

callback - 如何在 Dojo 中的另一个函数(非 AJAX)完成后调用一个函数(非 AJAX)?

javascript - 为什么捕获阶段不会被 event.stopPropagation 打断?

unit-testing - 单元测试自调用函数

javascript - 如何将监听器附加到克隆的元素?

javascript - 从不同域的页面返回时,如何让 Firefox 触发 popstate 事件?

javascript - 将 json 数据转换为附加方法的对象的最简单方法?

javascript - 如何使用 JSPM 使用缩小的第三方 Javascript 文件

javascript - ajax net::ERR_EMPTY_RESPONSE 等待响应 2 分钟后 - node.js 服务器

javascript - 推迟 Vue block 的渲染,直到数据加载