상단의 코드에서 P라는 부분을 클릭하면, 당연히 onclick으로 된 alert창이 띄워진다. 그런데 alert창에서 확인을 눌러 alert창을 제거하면 div라는 문구의 alert창이 띄워진다. 또 확인을 눌러 제거하면 또 다시 form 이라는 문구의 alert창이 뜨게 된다.
왜 P라는 부분만을 클릭했는데, 클릭하지도 않은 div와 form의 onclick이 작동했을까?
바로, 이벤트버블링이 동작했기 때문이다
위의 예시처럼 이벤트버블링의 원리는,
한 요소에 이벤트가 발생하면, 해당 요소에 할당된 핸들러가 동작하고, 이어서 바로 위의 부모요소의 핸들러가 동작한다. 계속 이어나가 최상단의 조상요소를 만날때까지 중간의 요소들에 할당된 핸들러들이 각각 동작한다.
가장 아래쪽의 자식요소인 <p>
태그를 클릭하면 하단의 순서로 버블링이 동작한다.
<p>
에 할당된 onclick
핸들러가 동작. (alert(P))<div>
에 할당된 핸들러가 동작. (alert(div))<form>
에 할당된 핸들러가 동작. (alert(form))document
객체를 만날때까지 각 요소에 할당된 핸들러들이 동작한다.이렇게 동작하기 때문에 <p>
태그만 클릭했을 뿐인데 <form>
태그의 핸들러까지 작동하게 된 것이다. 이런 흐름을 이벤트 버블링
이라 하고, 제일 깊은 곳의 요소부터 시작해 제일 상단의 요소까지 올라가며 발생하는 모양이 거품(bubble)과 같은 모양이기 때문에 이벤트 버블링
이라 한다.
부모요소의 핸들러는 이벤트가 어디에서 발생했는지 등의 자세한 정보를 얻을 수 있다.
여기서 보통 이벤트가 일어난 요소를 잡아내는 event.target과 this(= event.currentTarget)로 버블링의 동작확인 및 두 가지의 차이점을 알 수 있다.
상단의 예시처럼, 핸들러는 <form>
태그에만 할당되어 있지만, <p>
태그를 클릭해도 핸들러는 작동한다. 그 이유는 클릭이라는 이벤트가 어디서 발생했던지간에, 상단의 <form>
요소까지 이벤트가 버블링되어 <form>
요소에 있는 핸들러를 실행시키기 때문이다.
이것으로 알 수 있는 것은, 이벤트 버블링을 통해 해당요소의 자식요소들의 정보들을 가져올 수 있다는 것이다.
버블링은 꽤 유용하기 때문에, 버블링을 꼭 멈춰야하는 이유가 있는 상황을 제외하고는 버블링을 막지 않는다.
그래도 버블링을 멈추고 싶으면 해당 요소에 event.stopPropagation() 이라는 메서드를 사용해 바로 부모요소의 버블링을 멈출 수 있다.
하지만 부모요소의 버블링을 멈춘 뒤, 또 그 상단의 요소의 버블링은 멈춰지지 않는다. 모든 버블링을 멈추기 위해서는 event.stopImmediatePropagation() 이라는 메서드를 사용해 멈출 수 있다.
참고자료
버블링과 캡쳐링