캡쳐링 시기와 버블링 시기는 브라우저에서 이벤트를 처리하는 순서와 밀접하게 관련이 있다. 일반적으로 이벤트리스너(콜백함수)를 등록하게 되면 기본적으로 버블링 단계에서 등록된 콜백함수가 호출이된다.
(대부분의 캡처링 단계에서 무언가를 처리해줘야 했던 적은 없다. 기본적으로 버블링 단계에서 특정 이벤트를 처리 해주게되고, 이벤트 위임을 활용하게 된다.)
wrapper.addEventListener("click", (event) => {
console.log(`wrapper: ${event.currentTarget}, ${event.target}`);
}, { capture: true, }
);
<div>
<span>버블링</span>
</div>
<div>
<span>Click</span>
</div>
<script>
const parent = document.querySelector('div');
const children = document.querySelector('span');
parent.addEventListener('click', e => {
console.log('부모 event');
});
children.addEventListener('click', e => {
console.log('자식 event');
});
</script>
위의 사진을 보면, Click을 누르면 오른쪽의 console에 찍히는 것과 같이 span의 event를 발동시켰는데, 부모인 div의 함수도 같이 실행되는 것을 알 수 있다.
만약, 자식의 event만 실행시키고 싶을 때에는 2가지 방법이 있다.
<div>
<span>Click</span>
</div>
<script>
const parent = document.querySelector('div');
const children = document.querySelector('span');
parent.addEventListener('click', e => {
console.log('부모 event');
});
children.addEventListener('click', e => {
e.stopPropagation();
console.log('자식 event');
});
</script>
위와 같이 stopPropagation() 메서드를 자식의 이벤트에 적용시켰을 때, 부모에게 전파되는 버블링 단계를 전파되지 않도록 방지하는 방법이다. 그러나 stopPropagation 메서드를 사용하는 것은 좋지 않은 방법이다. 왜냐하면 다른 이벤트가 어떤 특별한 기능을 수행할 수 있는데, 본인의 이벤트만 처리하고 다른 이벤트를 수행하는 것들을 다 취소해버리는 방법이기 때문에 위험한 방법이다. 혹여나 프로젝트 규모가 커지면 이것 때문에 예상하지 못한 오류가 발생되어서 디버깅을 오랫동안 할 수 있을 것이다. 그러므로 웬만하면 쓰지 않는 것이 좋다.
<div>
<span>Click</span>
</div>
<script>
const parent = document.querySelector('div');
const children = document.querySelector('span');
parent.addEventListener('click', e => {
console.log(e.target);
console.log(e.currentTarget);
if (e.target !== e.currentTarget) {
return;
}
console.log('부모 event');
});
children.addEventListener('click', e => {
console.log('자식 event');
});
</script>