3장 DOM 이벤트 관리

namu·2025년 1월 5일

Event에 여러 의미를 부여할 수 있겠지만, 지금부터 interface EventEvent라고 칭하겠습니다.

Event란?

웹 어플리케이션에서 발생하는 동작을 말합니다.
그리고 이벤트가 발생(trigger)되는 노드를 EventTarget 이라고 부릅니다.

이벤트는 사용자에 의해 발생할 수도 있고, 시스템 자체에 코드를 통해 발생시킬 수도 있습니다.

이벤트 인터페이스를 상속받는 Event 종류는 마우스 이벤트, 키보드 이벤트, 뷰 이벤트 등이 있습니다.

이벤트에 반응하기 위해서는(accept/listen for),
이벤트를 트리거한 DOM 요소에 EventHandlers가 연결(connected/attached)되어 있어야 합니다.

EventHandler 연결하기

방법은 크게 두 가지가 있습니다.
: 속성(property)에 연결하기, addEventListener 사용하기

방법1) property에 연결하기

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

button.onclick = () => {
	console.log('Click managed using onclick property')
}

속성을 통해 연결하는 방법은 권장하지 않는데, 한 번에 하나의 핸들러만 연결할 수 있기 때문입니다.
속성에 코드가 덮어씌어지면 기존 핸들러는 영원히 사라집니다.

방법2) addEventListeners 사용하기

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

button.addEventListener('click', () => {
	console.log('clicked using addEventListener')
}, false)

button.addEventListener('click', () => {
  console.log('more handlers can be attached by addEventListeners')
},false)

addEventListeners는 property에 연결하는 방법과 달리 여러 이벤트 핸들러를 한 요소에 추가할 수 있습니다. (같은 이벤트 포함)

또한, removeEventListeners 메서드를 사용하면 해당 DOM 요소가 존재하지 않을 때 메모리 누수 방지를 위해 이벤트 핸들러를 삭제할 수도 있습니다.

// ...
const eventHandler = () => {
  console.log('event handler attached')
}

button.addEventListener('click', eventHandler, false)

//...

button.removeEventListener('click', eventHandler)


이벤트 객체

// ...
button.addEventListener('click',(e) => {
  console.log(e)
})

위의 핸들러가 실행되면 이벤트 객체를 조회할 수 있습니다.

⬇️



DOM 이벤트 라이프사이클

addEventListener 메서드를 사용해 핸들러를 추가하는 코드에는 일반적으로 다음과 같은 내용이 포함됩니다.

button.addEventListener('click', handler, false )
// 이벤트 이름, 이벤트 핸들러, useCapture

useCapture

<div>
  this is container
  <button> this is button </button>
</div>
//...
div.addEventListener('click', () => {
  console.log('div is clicked')
}

button.addEventListener('click', () => {
  console.log('button is clicked')
}

위의 상황에서 버튼을 클릭하면 콘솔에 어떻게 출력이 될까요?
하나만 ? 둘 다 ? 순서는 어떻지?

button is clicked
div is clicked

button 이 div 안에 있으므로 button부터 시작해서 두 핸들러가 모두 호출됩니다.
즉, 이벤트 객체는 이를 트리거한 DOM 노드에서 시작해 모든 조상 노드로 올라갑니다.

그리고 이러한 메커니즘을 버블단계(bubble phase) 혹은 이벤트 버블링(event bubbling)이라고 합니다.

useCapturetrue로 설정하면 핸들러의 실행 순서를 반대로 만들 수 있습니다.

즉, 버블단계 대신 캡처 단계에서 이벤트 핸들러를 추가한다는 의미입니다.

//...
div.addEventListener('click', () => {
  console.log('div is clicked')
}, false)

button.addEventListener('click', () => {
  console.log('button is clicked')
}, false)

// div is clicked
// button is clicked

버블 단계에서는 핸들러가 상향식(bottom-up)으로 실행된다면,
캡처 단계에서는 하향식(top-down)으로 실행됩니다.



사용자 정의 이벤트

CustomEvent 생성자 함수를 사용하여 사용자 정의 이벤트를 생성할 수 있습니다.

그리고,다른 이벤트와 동일하게 처리할 수 있습니다.

const EVENT_NAME = 'FiveCharInputValue';
const input = document.querySelector('input');

input.addEventListener('input',() => {
  const {length} = input.value
  console.log('input length:::',input.value.length)
  if(length === 5 ){
    const time = (new Date()).getTime()
    const event = new CustomEvent(EVENT_NAME, {
      detail: {
        time
      }
    })
    
    input.dispatchEvent(event)
  }
})

input.addEventListener(EVENT_NAME, ()=> {
  console.log('handling custom event')
})
profile
web dev

0개의 댓글