본문 바로가기

DEV/Note

JavaScript 이벤트 처리

개요

이 글은 JavaScript를 사용할 때 많이 작업하게 되는 이벤트 처리에 대해 정리한 내용입니다. 간단하게 아래 4가지에 대해서만 알아보겠습니다.

  • 이벤트 처리기 등록
  • 이벤트 처리기 제거
  • 이벤트 전파
  • 이벤트 취소

이벤트 처리기 등록

우리가 웹사이트를 이용하며 버튼을 클릭하거나 스크롤을 내릴 때 JavaScript에서는 이 행동들을 이벤트라고 부릅니다. 이벤트가 발생한 DOM에는 이벤트 인터페이스를 기반으로한 객체가 전달되는데, EventTarget.addEventListener 메서드를 사용하여 이벤트 객체를 전달 받을 수 있습니다.

문법

EventTarget.addEventListener(type, listener [, options]);
EventTarget.addEventListener(type, listener [, useCapture]);

매개변수

  • type
    수신 할 이벤트 유형을 나타내는 대소 문자 구분 문자열.
  • listener
    지정된 타입의 이벤트가 발생했을 때, 실행할 콜백함수입니다. 첫번째 파라미터에 이벤트 객체가 전달됩니다.
  • useCapture (선택 옵션)
    DOM 트리의 하단에 있는 EventTarget으로 전송하기 전에, 등록된 listener로 이 타입의 이벤트의 전송여부를 나타내는 Boolean 입니다.
    값이 true 이면 DOM 트리의 하단에 있는 EventTarget으로 이벤트가 전송되기 전에 탈취할 수 있습니다. 기본값은 false입니다.
  • options (선택 옵션)
    • capture
      useCapture 옵션과 동일합니다.
    • once
      리스너를 추가한 후 한 번만 호출되어야 함을 나타내는 Boolean입니다. true이면 호출할 때 listener 가 자동으로 삭제됩니다.
    • passive
      true일 경우, listener에서 지정한 함수가 preventDefault()를 호출하지 않음을 나타내는 Boolean입니다.

예제

window.addEventListener('scroll', function(event) {
  console.log(event)
}, false)

이벤트 처리기 제거

한번 등록한 이벤트 처리기는 once 옵션을 사용하지 않는 한 수동으로 이벤트 처리기를 제거할 때까지 이벤트를 처리합니다.

수동으로 이벤트 처리기를 제거하기 위해서는 EventTarget.removeEventListener 메서드를 사용하셔야됩니다. 등록했던 이벤트 처리기의 이벤트 type과 listener 함수 자체의 조합으로 식별되어 일치한 경우에만 이벤트 리스터가 제거되는데, 만약 옵션을 입력했다면 옵션의 값도 일치해야만 제거할 수 있습니다.

문법

EventTarget.removeEventListener(type, listener [, options]);
EventTarget.removeEventListener(type, listener [, useCapture]);

매개변수

  • type
    제거할 이벤트 리스너의 이벤트 타입을 지정합니다.
  • listener
    EventTarget에서 제거할 이벤트 listener 함수를 지정합니다. 등록한 listener 함수와 일치해야됩니다.
  • useCapture (선택 옵션)
    등록할 때 입력한 값과 일치해야만 이벤트 처리기가 제거됩니다.
  • options (선택 옵션)
    • capture
      등록할 때 입력한 값과 일치해야만 이벤트 처리기가 제거됩니다. capture 프로퍼티 외 다른 프로퍼티는 값이 일치하지 않아도 무관합니다.

예제

element.addEventListener("mousedown", handleMouseDown, true);

element.removeEventListener("mousedown", handleMouseDown, false); // 실패
element.removeEventListener("mousedown", handleMouseDown, true); // 성공

element.addEventListener("mousedown", handleMouseDown, { passive: true });

element.removeEventListener("mousedown", handleMouseDown, { passive: true }); // 성공
element.removeEventListener("mousedown", handleMouseDown, { capture: false }); // 성공
element.removeEventListener("mousedown", handleMouseDown, { capture: true }); // 실패
element.removeEventListener("mousedown", handleMouseDown, { passive: false }); // 성공
element.removeEventListener("mousedown", handleMouseDown, false); // 성공
element.removeEventListener("mousedown", handleMouseDown, true); // 실패

모든 이벤트 처리기 제거

구글링을 하면서 알게된 방법인데, 이 방법으로 이벤트 타겟에 등록된 모든 이벤트 처리기를 제거할 수 있습니다.

var old_element = document.getElementById("btn");
var new_element = old_element.cloneNode(true);
old_element.parentNode.replaceChild(new_element, old_element);

출처 : How to remove all listeners in an element?

저는 사실 이 방법이 마음에 들지 않아서 이벤트 처리기를 등록할 때 배열에 저장해놓고 컴포넌트를 제거할 때 배열에 있는 모든 이벤트를 순회하며 제거하는 방법으로 구현하였습니다.

이벤트 전파 차단

이벤트는 한번 실행되면 DOM Tree를 통해 부모와 자식 Node로 전파되는데, 자식 Node로 전파되는 것을 캡쳐링이라 하고 부모 Node로 전파되는 것을 버블링이라고 합니다. 이벤트 처리기가 복잡하게 얽힌 경우 의도치않은 문제가 발생할 수 있는데 Event.stopPropagation 메서드를 사용하여 현재 이벤트 이후의 전파를 막을 수 있습니다.

Button.addEventListener('click', function(event) {
  event.stopPropagation();
})

출처 : Event.stopPropagation() - Web API | MDN

이벤트 취소

어떤 이벤트에 대해 실행을 취소하고 싶은 경우 Event.preventDefault 메서드를 사용하여 이벤트를 취소할 수 있습니다. 단, 이벤트가 취소되도 이벤트의 전파는 막지않으며 Event.cancelabletrue일때만 취소할 수 있습니다.

Form.addEventListener('submit', function(event) {
  event.preventDefault(); // Form의 submit는 실행되지 않습니다.
})

Textarea.addEventListener('keydown', function(event) {
  if (event.key === 'Enter') {
    event.preventDefault(); // Textarea에서 Enter 키는 실행되지 않습니다.
  }
})

출처 : Event.preventDefault() - Web API | MDN

참고사이트

EventTarget.addEventListener() - Web API | MDN
EventTarget.removeEventListener() - Web API | MDN
이벤트 참조 | MDN
How to remove all listeners in an element?
Event.stopPropagation() - Web API | MDN
Event.preventDefault() - Web API | MDN