이번에는 이벤트가 어떻게 전파되는지 알아보자. 이런 코드가 있다. body 안에 div 안에 ul 안에 li가 있다. 이 모든 요소에 클릭 이벤트가 발생시 console.log()를 찍도록 만들 것이다.
이렇게 하고 li를 클릭해보면
li, ul, div, body 순서로 로그가 찍힌 걸 볼 수 있다. 초록색 박스를 클릭해보면 자기 자신인 div와 부모 요소인 body가 모두 찍힌다. 이를 통해 알 수 있는 것은 자식 요소에서 발생된 이벤트 객체는 부모와 그 부모를 통해 전달된다는 것이다. 즉 하위 요소에서 상위 요소로 올라가는 것이다. 더 이상 부모 요소가 없을 때까지 이 과정은 반복된다.
이렇게 DOM 트리가 있다. li에서 클릭 이벤트가 발생하면 부모 요소로 이렇게 전파된다. 이벤트가 거슬러 올라가는 모습이 물 속의 거품처럼 보인다. 이를 이벤트 버블링이라고 한다.
대부분의 이벤트는 버블링으로 전파되지만 일부는 그렇지 않다. focus와 blur가 그 예이다. 만약 이 이벤트들이 발생되었을 때 상위 요소에서 캐치하려면 이런 이벤트들로 대체해주면 된다. 왼쪽과 오른쪽 이벤트는 동작은 같지만 버블링에서 차이가 난다.
예제를 통해 살펴보자. body 안에 div 안에 input이 있다. 각각의 요소들은 focus 이벤트가 발생하거나 blur 이벤트가 발생할 때 로그를 찍어준다.
input 창에 focus를 하게 되면 3번 input만 찍힌다. focus를 벗어나도 동일한 요소만 찍힌다.
이때 focus를 focusin으로 blur를 focusout으로 바꿔준다.
input에 focus가 되면 input, div, body 순서로 찍힌다. 버블링이 되는 것이다. focus가 벗어나도 부모 요소들이 모두 찍히는 걸 볼 수 있다.
참고로 이벤트 버블링은 인위적으로 막을 수 있다. input 요소에 event.stopPropagation()을 실행해주면 된다. focusout에도 똑같이 만들어준다.
테스트해보면 focusin인데도 불구하고 이벤트 버블링이 발생하지 않는다. focusout도 마찬가지이다. 사실 이벤트 버블링을 막아야 하는 경우는 거의 없기 때문에 자주 사용되지는 않는다.
출처: 자바스크립트 DOM & EVENT #6 이벤트 버블링, 이벤트 위임