Events are actions or occurrences that happen in the browser, which you can respond to with JavaScript. Understanding events is crucial for creating interactive web applications.
In order to add an event listener to an element, you can use the EventTarget.addEventListener() method. Yet, in some cases, adding a listener for every single element can be a bit of a performance hit.
In these cases, you can use event delegation to add a single event listener to a parent element and then check if the event target matches the target you’re looking for.
const on = (el, evt, fn, opts = {}) => { const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); el.addEventListener( evt, opts.target ? delegatorFn : fn, opts.options || false ); if (opts.target) return delegatorFn;};const fn = () => console.log('!');on(document.body, 'click', fn);// logs '!' upon clicking the `body` elementon(document.body, 'click', fn, { target: 'p' });// logs '!' upon clicking a `p` element child of the `body` elementon(document.body, 'click', fn, { options: true });// logs '!' upon clicking on the `body` element,// but uses capturing instead of bubblingon(document.body, 'click', fn, { target: 'p', options: { once: true} });// logs '!' upon clicking a `p` element child of the `body` element,// but only once
Event delegation is more efficient when you have many elements with the same event listener, as it requires only one listener instead of many.
Removing an event listener from an element is as easy as adding one. You can use the EventTarget.removeEventListener() method to remove an event listener from an element.
const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);const fn = () => console.log('!');document.body.addEventListener('click', fn);off(document.body, 'click', fn);// no longer logs '!' upon clicking on the pageconst delegatorFn = on(document.body, 'click', fn, { target: 'p' });off(document.body, 'click', delegatorFn);// no longer logs '!' upon clicking a `p` element child of the `body` elementconst delegatorFnCapturing = on(document.body, 'click', fn, { options: true });off(document.body, 'click', delegatorFnCapturing, { options: true });// no longer logs '!' upon clicking on the page// (capturing instead of bubbling example)
You must pass the same function reference to removeEventListener that you passed to addEventListener. Arrow functions and anonymous functions won’t work for removal.
JavaScript’s EventTarget.dispatchEvent() method allows you to trigger an event programmatically. This method accepts an Event object as its only argument, which can be created using the CustomEvent constructor.
child.addEventListener('click', (e) => { e.stopPropagation(); console.log('Child clicked, event won\'t bubble to parent');});parent.addEventListener('click', () => { console.log('This won\'t be called when child is clicked');});
// Event fires during capture phase (top to bottom)element.addEventListener('click', handler, true);// Or with options objectelement.addEventListener('click', handler, { capture: true });