ul
태그 안에 li
태그들이 나열되어 있는 코드가 있다고 생각해보자. selected 라는 클래스를 선택자로 지정해 배경색을 노란색으로 스타일링하고, li
가 클릭되면 selected 클래스를 추가해서 배경색을 바꾸는 작업을 할 것이다.
const lis = document.querySelectorAll("li");
lis.forEach((li) => {
li.addEventListener("click", () => {
li.classList.add("selected");
});
});
해당 코드는 li
태그들을 querySelectorAll
로 모두 받아와 각각의 태그들에 이벤트 리스너를 등록하는 코드이다. 이렇게 일일히 모든 자식 노드들에게 이벤트 리스너를 등록하는 것은 비효율적이다.
여기서 포인트는 부모는 모든 자식의 이벤트를 듣고 있다는 것이다.
const ul = document.querySelectorAll("ul");
ul.addEventListener("click", (event) => {
if (event.target.tagName == "LI") {
event.target.classList.add("selected");
}
});
부모는 자식에게 일어나는 이벤트를 모두 듣고 있다. 이유는 이전에 작성한 이벤트 캡쳐링
때문이다. 캡쳐링
은 이벤트 위임
이 가능하도록 하는 중요한 개념이다.
자식 노드에서 발생하는 이벤트는 부모 노드까지 캡쳐링
단계를 거치기 때문에 부모 노드에 이벤트를 등록한다면 자식 노드에서 발생하는 이벤트를 부모 노드에서 처리할 수 있다.
따라서 위의 코드를 개선해 li
태그에 이벤트를 등록하는 것이 아니라 부모 노드인 ul
태그에 이벤트를 등록해서 현재 이벤트가 발생한 지점인 target
의 태그명을 확인하여 li
이면 클래스를 추가해주는 코드로 이벤트를 처리하였다.