DEV Community

Filip Biterski
Filip Biterski

Posted on • Updated on

The problem with DOM’s event listeners

The way we add and remove event listeners on DOM elements hasn’t change much for two decades. It's methods: addEventListener, and removeEventListener do a decent job, but if we want to dynamically add and remove the listeners, these methods become impractical.

Let’s see why is that so, and consider a potential solution.

The problem

This is how an event listener is registered on the target element:

target.addEventListener(type, listener, options);

And this is how it’s removed:

target.removeEventListener(type, listener, options); 

The problem with this is the fact that removeEventListener method, requires parameters of identical value the listener was registered with, requiring us to save and keep track of these parameters.

For each registered listener that we might want to remove later, we would need to store it’s defining variables: target, type, and listener.

Imagine how cluttered our code would become if we register a dozen removable event listeners. We would potentially need a lot of variables... This practice then becomes cluttery and repetitive.

The solution

A better way DOM could handle this is if the addEventListener method would return an instance of the subscription object which would hold all the defining parameters. Such object instances could hold methods like ‘unmount’, ‘mount’, or ‘update’...

So instead of just registering the listener, we could also reference the subscription:

const sub1 = target.addEventListener(type, listener, options); 

Unmount the subscription:

sub1.unmount();

// instead of this:
target.removeEventListener(type, listener, options);

Update the subscription:

sub1.update({name: type2});

// instead of this:
target.removeEventListener(type, listener, options); 

target.addEventListener(type2, listener, options); 

Good news is that I've made a library that implements this idea: It’s called Subvent and You can read more about it here...

... or start using it straight away:

GitHub logo filiBit / subvent

Define and manage DOM Event subscriptions

Subvent

Create event subscriptions in DOM. Manage them with update, unmount and mount methods.

Abstracts DOM's addEventListener, and removeEventListener methods into a subscription object.

Installation

In node projects:

npm install --save subvent
import {Subvent} from 'subvent'
// or use the shorthand:
import {on} from 'subvent'

In browsers:

<head>
  <script src="https://unpkg.com/subvent@latest/dist/iife/subvent.js"></script>
</head>

Usage

Get the DOM nodes first:

const el1 = document.getElementById('element-1');
const el2 = // ...
const el3 = // ...
const el4 = // ...

Define the event subscription

const evtSub1 = new Subvent(el1, 'click', () => {...});
  • creates an instance of Subvent
  • the instance represents an event subscription

The shorthand on function is also available:

const evtSub2 = on(el2, 'click', (

Discussion (9)

Collapse
abdisalan_js profile image
Abdisalan

Awesome post! Learned a problem and was served the solution

Collapse
lallenfrancisl profile image
Allen Francis

This idea is pretty much used as a starting point and then expanded into a whole paradigm for observables and rxjs.

youtube.com/playlist?list=PL55RiY5...

rxjs.dev/guide/overview

Collapse
ranguna profile image
Luis Pais

I don't understand how the solution would solve the "save and keep track of these parameters" since you'd still need to "save and keep track" of the return value of addEventListener.

Collapse
filibit profile image
Filip Biterski Author • Edited on

Well, it's a single variable per subscription, instead of many. Maybe I should have worded it better. :)

Collapse
jivkojelev91 profile image
JivkoJelev91

Whole library for two methods? Don`t know dude.

Collapse
filibit profile image
Filip Biterski Author

A little more then that, but yes. I understand people are sceptical. The lib is most usefull for larger event-driven apps to help with organizing subscriptions.

Collapse
shahrozahmd profile image
Shahroz Ahmed

is "unmount();" is specifically your developed library's method?? because console through me an error that there is nothing like "unmount();" is available in javascript.

Collapse
filibit profile image
Filip Biterski Author • Edited on

Yes. If You want to use it, read installation instructions in the repository.

Collapse
shahrozahmd profile image
Shahroz Ahmed

Oh... sure I will use it :)