웹 페이지에서 입력 폼에 내용을 입력하거나, 버튼을 클릭하는 등 다양한 이벤트가 발생한다. 이벤트 흐름 (Event Flow)은 이러한 이벤트가 발생했을 때, 그 이벤트를 전파하는 흐름을 말한다. 이벤트 흐름은 캡처링 단계 → 타깃 단계 → 버블링 단계의 순서로 발생한다.
캡처링 단계에서는 이벤트가 하위 요소로 전파된다. 최상위 요소에서부터 이벤트가 전파되며 DOM 트리를 따라 타깃요소까지 트리를 따라 내려가면서 addEventListener(..., true)
로 할당한 핸들러를 동작시킨다. 이 단계를 캡처링 단계라고 할 수 있다.
핸들러의 동작을 확인하려면 addEventListener
메서드에서 capture
옵션을 true
로 설정하거나 세 번째 파라미터를 true
로 전달함으로써 캡처링 단계에서의 이벤트를 확인할 수 있다. (기본적으로 false
로 되어 있어 버블링 단계에서 동작함)
이벤트가 실제 타깃 요소에 전달되는 단계이다. 이 단계에서 타깃에 등록된 핸들러가 동작한다.
이벤트가 상위 요소로 전파되는 단계이다. 타깃 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작한다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작하게 되는 것이다.
이벤트가 상위 요소로 전파되면서 핸들러가 동작하기 때문에 원치 않는 동작을 실행시킬 수 있다. 이때, 버블링을 방지하기 위한 방법을 사용할 수 있다.
stopPropagation()
메서드를 사용해 이벤트 전파를 방지할 수 있다. 하지만 이벤트의 전파만 방지하고 링크나 버튼의 클릭과 같은 기본적인 동작은 진행되므로 이를 방지하려면 preventDefault()
메서드를 사용해야 한다. 또한 같은 대상에 포함된 다른 핸들러의 동작을 방지하지는 못한다.
stopImmediatePropagation()
메서드를 사용하면 현재의 이벤트를 실행하고 같은 대상에 적용된 다른 핸들러의 동작까지 방지한다.
앞서 언급한 캡처링과 버블링을 사용해 이벤트 위임이라는 방법을 사용할 수 있다. 이벤트 위임이란 하위 요소에 대한 이벤트 처리를 상위 요소에서 처리하는 방식을 말한다. 다수의 요소에 공통으로 적용되는 이벤트 핸들러를 공통된 조상 요소에 단 한 번만 연결하면 동작할 수 있도록 한다. 동적으로 생성한 요소에 대해 이벤트 리스너를 추가할 수 있으면서 코드를 간편하게 만들어 유지보수의 편리성도 확보할 수 있다.
아래의 예시는 버튼이 생성된 시간을 alert로 보여주는 버튼을 동적으로 생성하는 버튼이 있는 웹 페이지이다.
버튼을 만들 때마다 이벤트 리스너를 등록하여 생성할 수도 있지만, 이벤트 핸들러가 많아질 경우 웹 페이지의 성능 저하를 일으킬 수 있다. 이벤트 위임을 통해 버튼들을 포함하는 요소에 클릭 이벤트를 부여하여 event.target
속성을 통해 이벤트 타깃이 버튼일 경우에만 이벤트를 처리하는 로직을 쓸 수 있다.
toLocaleString()
메서드를 통해 현재의 날짜, 시간을 내용으로 새로운 버튼을 생성하고, setAttribute()
메서드로 alert에 표시할 값을 저장할 속성을 생성한다. 속성의 내용은 toLocaleTimeString()
메서드를 통해 받은 현재의 시간이 된다.
버튼들을 포함할 영역인 <section id="buttonGroup">
에 클릭 이벤트 리스너를 부여한다. 이벤트 내용은 타깃의 부모 요소(closest()
메서드 사용하여 찾음) 중 buttonTime
클래스를 갖는 요소가 있을 경우, 즉 타깃 요소가 누르면 시간을 표시할 버튼일 경우 해당 버튼이, 그렇지 않으면 null
이 저장된다. if(targetButton)
에서 null
일 경우 if
안의 로직을 실행하지 않고 그렇지 않으면 alert로 앞서 설정한 현재 시간을 나타낸다.
DevStory) [JS]이벤트 흐름(Event Flow) 이해하기
JAVASCRIPT.INFO) 버블링과 캡처링
PoiemaWeb) Event
메모를 메모하다) [Javascript] 이벤트 버블링 방지 stopImmediatePropagation
JAVASCRIPT.INFO) 이벤트 위임