DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파된다. 이를 Event Propagation이라고 한다. 예시를 통해 이해해보자.
<div onclick="alert('div1')">div1
<div onclick="alert('div2')">div2
<div onclick="alert('div3')">div3</div>
</div>
</div>
위 코드와 같이 각
div요소에 클릭 이벤트 핸들러를 할당하고 가장 안쪽에div요소를 클릭하면 어떻게 될까???
일반적인 생각으로는 가장 안쪽에 div요소를 클릭했기 때문에 div3 alert box만 출력될 것 같지만 실제로는 div3 -> div2 -> div1 순으로 3개의 alert box가 출력된다.
위와 같은 현상이 발생하는 이유는 Event Propagation때문이다.
가장 안쪽에 div요소를 클릭하면 클릭 이벤트가 발생한다. 이때 생성된 이벤트 객체는 이 이벤트를 발생시킨 DOM 요소인 Event Target을 중심으로 DOM 트리를 통해 전파된다.
이벤트 전파는 이벤트 객체가 전파되는 방향에 따라 위 이미지와 같이 3단계로 구분된다.
위의 예시를 이용해 다시 설명해보면, 가장 안쪽에 div요소를 클릭하면 클릭 이벤트가 발생하여 클릭 이벤트 객체가 생성되고 클릭된 div요소가 이벤트 타겟이 된다.
클릭 이벤트 객체는 window에서 시작해서 이벤트 타겟 방향으로 전파된다. 이것이 Capturing 단계이다.
이후 이벤트 객체는 이벤트 타겟에 도달한다. 이것이 Target 단계이다. 이때 div3에 할당된 클릭 이벤트 핸들러가 실행된다.
그리고 이벤트 객체는 이벤트 타겟에서 시작해서 window방향으로 전파된다. 이것이 Bubbling 단계이다. 이때 div2 -> div1순으로 전파가 되면서 각각에 할당된 클릭 이벤트 핸들러가 실행된다.
이처럼 이벤트는 이벤트를 발생시킨 이벤트 타겟은 물론 상위 DOM 요소에서도 캐치할 수 있다.
즉, DOM 트리를 통해 전파되는 이벤트는 event path에 위치한 모든 DOM 요소에서 캐치할 수 있다.
대부분의 이벤트는 3단계를 통해 전파된다. (아닌 이벤트도 존재한다.)
Capturing phase의 이벤트를 캐치하는 경우는 흔치 않다.
attribute나 property 방식으로 등록한 이벤트 핸들러는 타겟과 버블링 단계의 이벤트만 캐치할 수 있다.
하지만 addEventListener 방식으로 등록한 이벤트 핸들러는 캡쳐링 단계의 이벤트도 선별적으로 캐치할 수 있다.
캡쳐링 단계의 이벤트를 캐치하려면 addEventListener의 3번째 인자로 true를 전달해야 한다. 생략하거나 false를 전달하면 타겟과 버블링 단계의 이벤트만 캐치할 수 있다.