简体   繁体   中英

How to capture custom events?

I am trying to create a custom event and capture that event. Here is my simplified HTML and JavaScript

 let parent = document.getElementById('parent'); let child = document.getElementById('child'); parent.addEventListener('custom-event', () => alert("parent"), true); child.addEventListener('custom-event', () => alert("child")); let event = new Event('custom-event'); parent.dispatchEvent(event);
 <div id="parent"> <p id="child"> Hello World </p> </div>

In this case I get the alert "parent" but then I don't get the child popup.

However, If I try using already existing event like "click", it works.

 let parent = document.getElementById('parent'); let child = document.getElementById('child'); parent.addEventListener('click', () => alert("parent"), true); child.addEventListener('click', () => alert("child"));
 <div id="parent"> <p id="child"> Hello World </p> </div>

Is there any way/work around that I can use to capture custom events?

As Moritz stated, you will need to fire the event on the child, as it is the most-inner element. That way the event bubbles up to each parent. The target of the event will always be the child, but currentTarget of the event will be the current element as it goes up the chain.

You must make sure that useCapture is true , for the ancestor elements you want the event to be picked-up for. See: EventTarget.addEventListener .

useCapture

A Boolean indicating that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.

Events that are bubbling upward through the tree will not trigger a listener designated to use capture. Event bubbling and capturing are two ways of propagating events that occur in an element that is nested within another element, when both elements have registered a handle for that event. The event propagation mode determines the order in which elements receive the event. See DOM Level 3 Events and JavaScript Event order for a detailed explanation. If not specified, useCapture defaults to false .

If you remove the useCapture param (the second param) from parent.addEventListener , only the grand-parent will get picked-up, following the child. It will not break the chain, unless you cancel the event in the child.

Note: If you are triggering a non-native event, it is preferred to use the CustomEvent constructor. Again, you could just call the constructor directly if you wanted. This is just a browser-safe wrapper.

 let grandParent = document.getElementById('x-grand-parent'); let parent = document.getElementById('x-parent'); let child = document.getElementById('x-child'); grandParent.addEventListener('custom-event', (e) => console.log(e.currentTarget.id), true); parent.addEventListener('custom-event', (e) => console.log(e.currentTarget.id), true); child.addEventListener('custom-event', (e) => console.log(e.currentTarget.id)); triggerCustomEvent(child, 'custom-event'); function triggerCustomEvent(el, eventName, options) { let opts = Object.assign({ canBubble: true, cancelable: true, detail: {} }, options); let event = null; if (window.CustomEvent && typeof window.CustomEvent === 'function') { event = new CustomEvent(eventName, { detail: opts.detail }); } else { event = document.createEvent('CustomEvent'); event.initCustomEvent(eventName, opts.canBubble, opts.cancelable, opts.detail); } el.dispatchEvent(event); }
 <div id="x-grand-parent"> <div id="x-parent"> <p id="x-child"> Hello World </p> </div> </div>

Try dispatching the event on the child node and you'll get both alerts.

 let parent = document.getElementById('parent'); let child = document.getElementById('child'); parent.addEventListener('custom-event', () => alert("parent"), true); child.addEventListener('custom-event', () => alert("child")); let event = new Event('custom-event'); child.dispatchEvent(event);
 <div id="parent"> <p id="child"> Hello World </p> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM