Skip to content
beginnerPhase 34 · DOM

Event Listeners

Attach and remove event listeners with addEventListener and removeEventListener.

30m
0 problems
Topic Progress0%

addEventListener

addEventListener attaches an event handler to an element.

Basic Usage

const button = document.querySelector('button');

// Add click handler
button.addEventListener('click', () => {
  console.log('Button clicked!');
});

// Named function (easier to remove)
function handleClick() {
  console.log('Clicked!');
}
button.addEventListener('click', handleClick);

Event Types

// Mouse events
button.addEventListener('click', handler);
button.addEventListener('dblclick', handler);
button.addEventListener('mousedown', handler);
button.addEventListener('mouseup', handler);
button.addEventListener('mouseover', handler);

// Keyboard events
document.addEventListener('keydown', handler);
document.addEventListener('keyup', handler);

// Form events
form.addEventListener('submit', handler);
input.addEventListener('input', handler);
input.addEventListener('change', handler);
input.addEventListener('focus', handler);
input.addEventListener('blur', handler);

// Window events
window.addEventListener('resize', handler);
window.addEventListener('scroll', handler);
window.addEventListener('load', handler);

Adding Multiple Listeners

// Same event, multiple handlers
button.addEventListener('click', firstHandler);
button.addEventListener('click', secondHandler);

// Both will execute
button.addEventListener('mousedown', handler1);
button.addEventListener('mouseup', handler2);

Options Object

button.addEventListener('click', handler, {
  capture: false,  // Listen in capturing phase
  once: true,      // Remove after first call
  passive: true,   // Never calls preventDefault()
  signal: abortController.signal // AbortController
});

// once: true - auto-remove after first call
button.addEventListener('click', () => {
  console.log('This runs only once');
}, { once: true });

// passive: true - for performance (scroll, touch events)
document.addEventListener('touchmove', handler, { passive: true });

Arrow Functions vs Named Functions

// Arrow function - can't remove (no reference)
button.addEventListener('click', () => {
  console.log('clicked');
});

// Named function - can remove
function handleClick() {
  console.log('clicked');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick);

removeEventListener

removeEventListener removes an event handler. Must pass the same function reference.

Basic Usage

function handleClick() {
  console.log('clicked');
}

// Add
button.addEventListener('click', handleClick);

// Remove (must pass same function reference)
button.removeEventListener('click', handleClick);

Common Mistake

// WRONG - anonymous function can't be removed
button.addEventListener('click', () => {
  console.log('clicked');
});
button.removeEventListener('click', () => {
  console.log('clicked');
}); // Doesn't work! Different function!

// CORRECT - use named function
function handleClick() {
  console.log('clicked');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick); // Works!

Cleanup Pattern

function setup() {
  const handler = (e) => console.log(e.target);
  
  button.addEventListener('click', handler);
  
  // Return cleanup function
  return () => {
    button.removeEventListener('click', handler);
  };
}

const cleanup = setup();
// Later:
cleanup(); // Removes listener

AbortController Pattern

const controller = new AbortController();

button.addEventListener('click', handler, {
  signal: controller.signal
});

// Remove all listeners with this signal
controller.abort();

// Can also abort after timeout
setTimeout(() => controller.abort(), 5000);

Event Listener Cleanup in Components

// React-like cleanup
useEffect(() => {
  const handler = () => { /* ... */ };
  window.addEventListener('resize', handler);
  
  return () => {
    window.removeEventListener('resize', handler);
  };
}, []);

// Class component
class Component {
  componentDidMount() {
    window.addEventListener('resize', this.handleResize);
  }
  
  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  }
}

Event Object

The event object contains information about the event.

Event Object Properties

button.addEventListener('click', (event) => {
  // Basic properties
  console.log(event.type);        // 'click'
  console.log(event.target);      // Element that triggered event
  console.log(event.currentTarget); // Element with listener
  console.log(event.timeStamp);   // When event occurred
  
  // Mouse properties
  console.log(event.clientX);     // X position
  console.log(event.clientY);     // Y position
  console.log(event.pageX);       // X relative to document
  console.log(event.pageY);       // Y relative to document
  
  // Keyboard properties
  console.log(event.key);         // 'Enter', 'a', etc.
  console.log(event.code);        // 'KeyA', 'Enter'
  console.log(event.altKey);      // Alt held
  console.log(event.ctrlKey);     // Ctrl held
  console.log(event.shiftKey);    // Shift held
  
  // Form properties
  console.log(event.target.value);
  console.log(event.target.checked);
});

Preventing Default Behavior

// Prevent form submission
form.addEventListener('submit', (e) => {
  e.preventDefault(); // Form won't submit
  // Handle with JavaScript
});

// Prevent link navigation
link.addEventListener('click', (e) => {
  e.preventDefault(); // Won't navigate
});

// Prevent context menu
document.addEventListener('contextmenu', (e) => {
  e.preventDefault(); // No right-click menu
});

Stopping Propagation

// Stop bubbling
document.addEventListener('click', (e) => {
  if (e.target.closest('.modal')) {
    e.stopPropagation(); // Won't bubble to document
  }
});

// Stop immediate propagation
button.addEventListener('click', (e) => {
  e.stopImmediatePropagation(); // Other listeners won't fire
  console.log('First handler');
});

button.addEventListener('click', () => {
  console.log('Second handler'); // Won't run
});

Event Delegation with Event Object

const list = document.querySelector('ul');

list.addEventListener('click', (e) => {
  // Find the list item
  const item = e.target.closest('li');
  
  // Check if click was on a list item
  if (item && list.contains(item)) {
    // Get item data
    const id = item.dataset.id;
    const text = item.textContent;
    
    // Handle click
    handleItemClick(id, text);
  }
});

Practice Problems

0/3solved
Build Event Listeners Component

Create a reusable React component implementing Event Listeners. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Event Listeners Testing

Write unit and integration tests for Event Listeners using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Event Listeners Performance

Optimize Event Listeners for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. Why can't you remove an anonymous event listener?

Question 1 options

2. What does e.preventDefault() do?

Question 2 options

3. What is the difference between target and currentTarget?

Question 3 options

4. What does the { once: true } option do?

Question 4 options

Flashcards

Question

How to add an event listener?

Answer

element.addEventListener('event', handler, options) - options include capture, once, passive, signal.

Question

How to remove an event listener?

Answer

element.removeEventListener('event', handler) - must pass the same function reference used in addEventListener.

Question

What is e.target vs e.currentTarget?

Answer

target: element that triggered the event. currentTarget: element with the listener attached.

Question

What does preventDefault() do?

Answer

Prevents the browser's default action (form submit, link navigation) but doesn't stop propagation.

Question

What is Event Listeners?

Answer

Event Listeners is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.addEventListener is the standard way to handle events
  • 2.You need the same function reference to remove listeners
  • 3.e.target is the clicked element, e.currentTarget has the listener
  • 4.preventDefault() stops browser default behavior
  • 5.Use { once: true } for one-time handlers

Interview Tips

  • Show how to properly add and remove event listeners
  • Explain the difference between target and currentTarget
  • Demonstrate event delegation patterns
  • Discuss when to use { passive: true } for performance

Cheat Sheet

Event Listeners Cheat Sheet

Adding Listeners

el.addEventListener('click', handler, options);

Options

  • capture: Listen in capturing phase
  • once: Remove after first call
  • passive: Can't call preventDefault()
  • signal: AbortController signal

Removing Listeners

el.removeEventListener('click', handler);

Event Object

  • e.target: Triggered element
  • e.currentTarget: Listener element
  • e.preventDefault(): Stop default behavior
  • e.stopPropagation(): Stop bubbling