Codeskill

Learn to code, step by step

Events (delegation, custom, cleanup)

Events properly – delegation, custom events, passive listeners, and cleanup. Beginner tutorials attach handlers to single buttons; real UIs need patterns that scale and do not leak memory.

Event delegation

const list = document.querySelector('#todo-list');

list.addEventListener('click', (event) => {
  const button = event.target.closest('[data-action]');
  if (!button || !list.contains(button)) return;

  const { action } = button.dataset;
  const item = button.closest('[data-id]');
  if (action === 'delete') removeItem(item.dataset.id);
  if (action === 'toggle') toggleItem(item.dataset.id);
});

closest walks up from the click target. One listener handles current and future rows.

Custom events

const cart = document.querySelector('#cart');

cart.addEventListener('cart:updated', (event) => {
  renderTotal(event.detail.total);
});

function emitCartUpdated(total) {
  cart.dispatchEvent(new CustomEvent('cart:updated', {
    bubbles: true,
    detail: { total },
  }));
}

Namespaced event names (cart:updated) reduce collisions with native events. Use detail for payload data.

Passive listeners for scroll/touch

window.addEventListener('scroll', onScroll, { passive: true });

Tells the browser you will not call preventDefault, so scrolling can proceed smoothly. Required for touch performance on mobile in many cases.

Cleanup with AbortController

const controller = new AbortController();
const { signal } = controller;

button.addEventListener('click', onSave, { signal });
fetch('/api/config', { signal }).then(render);

function teardown() {
  controller.abort(); // removes listeners using signal
}

One controller can unify DOM listeners and in-flight fetch for a component or modal lifecycle.

once and capture

{ once: true } removes the listener after the first fire – handy for intro tours or waiting for a transition. Capture phase ({ capture: true }) runs on the way down; rarely needed except for focus traps or intercepting before children.

Next: the constraint validation API for forms that behave well without reinventing every rule in JavaScript.

PreviousDOM performance