ul태그가 있고 얘가 li태그들을 자식들로 갖고 있다고 하자. 이 li태그들에 어떤 이벤트를 등록하려면 지금까지는 다음과 같이 해왔었다. 

<ul id="some-list">
    <li>가계부 정리하기</li>
    <li>자바스크립트 강의듣기</li>
    <li>리액트 공부하기</li>
    <li>코딩테스트 문제 풀기</li>
</ul>
const someList = document.getElementById("some-list");

for (let item of someList.children){
    item.addEventListener("click", function(e){
        e.target.ClassList.toggle("done");
    };
}

즉 자식들로 잡든 처음부터 getElementsByClassName으로 잡던 li태그들 하나하나에 직접 이벤트 리스너들을 때려박는 형태였다. 그러나 하나하나 때려박는다는 것이 성능상 안 좋기도 하고, 나중에 js코드로 some-list에 새로운 li태그를 넣을 경우 새로 넣어진 li태그에도 별도로 다시 저 이벤트를 때려박아야 하는 번거로운 일이 생긴다.

 

이런 상황에서 쓸 수 있는 것이 이벤트 위임.

간단하게 말해서, 자식들의 이벤트 리스너를 부모에서 다루는 것이다. 

이벤트 버블링을 통해서.

 

알다시피 이벤트 버블링은 자식에서 발생한 이벤트가 부모로 퍼져가는 것을 말한다. 즉 위와 같은 클릭 이벤트를 등록하는 상황에서, 자식(li태그)에서 발생한 click이벤트가 부모(ul태그 등)으로 퍼져나가는 것을 활용한다는 것이다. 그리고, e.target을 활용하면 이벤트를 발생시킨 녀석에 대한 특정한 동작 등이 가능하다!! 즉 다음과 같이 할 수 있다.

const someList = document.getElementById("some-list");

someList.addEventListener("click", function(e){
    if (e.target.tagName == "li"){
        e.target.ClassList.toggle("done");
    }
});

if (e.target.tagName == "li")를 넣은 이유는, ul태그의 영역에서 li태그가 없는 공간을 클릭하는 상황에도 저 이벤트 리스너가 수행되는 상황을 막는 것이다. 해석하자면 ul태그의 영역에 대해 클릭 이벤트가 발생했을 때 이벤트 리스너를 실행하는데 그 중에서도 ul 태그 내의 li태그가 클릭돼서 수행되는 경우에만 if문 내의 코드를 실행한다는 것. 

 

기존에 쓰던 반복문을 통해 하나하나 이벤트 리스너를 때려박는 방법이 비효율적이라곤 생각했으나 이렇게 쉬운 방법이 있을 줄 몰랐다. 강의를 듣던 중 관련된 질문에 "아니 이렇게 하면 부모에 등록되는 건데, 이 경우엔 자식에도 등록이 되어지는 거냐?"란 질문이 있던데, 내 생각은 "No. 아닙니다. 자식인 li태그를 클릭하면 캡처링 단계에서 수수숙 내려와 li태그 즉 사건을 불러일으킨 놈을 찍고, 다시 부모 요소들로 올라가는 버블링이 생기게 되는데 그 때 저 이벤트 리스너가 수행되면서 target을 통해 불러일으킨 놈이 내 자식 중에서 li일 때만 수행하는 방식입니다"이다.

 

참고로 이 이벤트 위임이란 방법은 버블링을 이용하는 방법이므로, 당연한 소리지만 자식 태그에 버블링을 막도록 코드를 짜놨으면 무용지물이다. 이 점 알아두고 사용하자.

+ Recent posts