Event Bubbling / Event Capturing
버블링과 캡쳐링을 본격적으로 알아보기 전에 간단한 코드를 한 번 살펴보자.
1 | <div onclick="alert('The DIV handler!')"> |
See the Pen Ryewge by SoyeonJung (@je_ss2) on CodePen.
div
태그에 alert('The DIV handler!')
라는 이벤트 핸들러를 할당하였고, p
태그에는 어떠한 핸들러도 할당하지 않았다. 그런데 p
태그를 클릭해도 div
태그에 할당된 핸들러가 실행이 된다.
조금 이상하다.
p
태그를 클릭했는데 왜div
태그에 할당된 핸들러가 실행이 되는 것일까?
버블링 때문이다.
자바스크립트의 이벤트 버블링 때문에 위의 코드에서 div
태그 안에 있는 p
태그를 클릭하면 div
태그에 할당된 클릭 이벤트가 발생하는 것이다.
그럼, 버블링이 정확히 뭔데?
이벤트 버블링의 원리는 간단하다.
“엘리먼트에 이벤트가 발생하면 먼저 해당 엘리먼트의 핸들러를 실행시킨 후, 그의 부모 엘리먼트의 핸들러를 실행시키고, 또 그 위의 조상 엘리먼트들의 핸들러를 실행시킨다”
마치 버블이 아래에서 위로 올라가는 것과 같아서 버블링이라고 한다. 아래의 예시를 보자.
1 | <form onclick="alert('form')">FORM |
See the Pen WJaNgQ by SoyeonJung (@je_ss2) on CodePen.
form
태그에는 alert('form')
클릭 이벤트를 줬고, div
태그에는 alert('div')
클릭 이벤트를 줬고, p
태그에는 alert('p')
클릭 이벤트를 줬다. 그런데, p
태그는 div
태그가 감싸고 있고, 또 그 div
태그는 form
태그가 감싸고 있다.
따라서 이벤트 버블링으로 인해, p
태그를 클릭하면 p -> div -> form
순서로 알림창이 뜬다. 그리고 div
태그를 클릭하면 div -> form
순서로 알림창이 뜬다.
p
태그를 클릭하면 window
에서부터 p
태그까지 요소 중간에 있는 이벤트들을 전부 검색해서 따로 메모리에 가지고 있다고 생각하면 된다. 해당 엘리먼트부터 차례대로 위로 올라가면서 이벤트들을 발생시키는 것, 그것이 바로 이벤트 버블링이다.
버블링 멈추기
기본적으로 이벤트 버블링은 항상 발생한다. 아래의 코드를 보자.
1 | <form onclick="alert('form')">FORM |
See the Pen WJabwo by SoyeonJung (@je_ss2) on CodePen.
form
태그와 div
태그에만 이벤트 핸들러를 주고, p
태그에는 이벤트 핸들러를 주지 않았다. 하지만, 이벤트 버블링으로 인해 p
태그를 클릭하면 div -> form
순서로 알림창이 뜬다.
이벤트 버블링이 발생되지 않았으면 좋겠어
이벤트 버블링은 event.stopPropagation()
을 이용해서 간단하게 멈출 수 있다. 아래의 코드를 보자.
1 | <form onclick="alert('form')">FORM |
See the Pen xjyGGK by SoyeonJung (@je_ss2) on CodePen.
p
태그에 onclick="event.stopPropagation()"
를 주었더니, p
태그를 클릭해도 아까처럼 이벤트가 발생하지 않는다. 이벤트 버블링이 작동하지 않기 때문이다.
이벤트 캡쳐링
그렇다면 이번에는 이벤트 캡쳐링에 대해서 알아보자. 이벤트 캡쳐링도 이벤트 버블링과 비슷하다. 버블링이 아래에서 위로 올라가는 것이라면, 캡쳐링은 위에서 아래로 내려가는 것이다.
addEventListener
를 이용하여 버블링과 캡쳐링에 대해서 살펴보자.
capturing
단계에서 이벤트를 catch
하려면 addEventListener
의 세 번째 요소를 true
로 설정해줘야 한다. 기본적으로 addEventListener
의 세 번째 요소를 작성하지 않으면 default
값이 false
인데, false
로 설정할 경우, 핸들러는 버블링 단계로 설정된다. 반면에 true
로 설정할 경우, 핸들러는 캡쳐링 단계로 설정된다.
먼저 addEventListener
의 세 번째 요소를 작성하지 않았을 경우를 살펴보자.
1 | <form>FORM |
1 | //JavaScript Code |
See the Pen mLzywJ by SoyeonJung (@je_ss2) on CodePen.
p
태그를 클릭하면 P -> DIV -> FORM -> BODY -> HTML
순서로 알림창이 열린다. addEventListener
의 세 번째 요소를 작성하지 않아서 기본값인 false
로 되었기 때문에 핸들러가 버블링 단계로 설정되었기 때문이다.
이번에는 addEventListener
의 세 번째 요소를 true
로 작성해보자.
1 | <form>FORM |
1 | //JavaScript Code |
See the Pen WJabBd by SoyeonJung (@je_ss2) on CodePen.
p
태그를 클릭하면 HTML -> BODY -> FORM -> DIV -> P
순서로 알림창이 열린다. addEventListener
의 세 번째 요소를 true
로 작성했기 때문에 핸들러가 캡쳐링 단계로 설정되었기 때문이다.