이벤트 버블링, 캡처링

myung hun kang·2022년 11월 5일
0

우리가 웹페이지에서 버튼을 클릭할 때 어떤 상호작용을 일으키는 기능을 만들었다고 해보자.

사람 눈에는 안 보이지만 웹페이지는 render tree에 따라서 자여지 여러개의 층으로 나누어져 있다. 이 층에서 어떻게 정확히 내가 클릭한 버튼에 기능을 부여할 수 있을까?

HTML DOM 트리

우리가 어떤 버튼을 클릭하는 화면을 만들었다고 했을 때 그 화면의 보이지 않는 Dom tree의 모습은 다음과 같다.

버블링 캡처링과 dom 트리

사실 우리가 버튼을 클릭했다고 버튼만 눌리는 것이 아니라 모든 상위 계층이 다 눌리게 되는 것이다.

버블링 캡처링

버튼 클릭시 브라우저는 window 노드부터 dom 요소들을 타고 버튼을 찾으러 내려간다. 이 과정이 바로 캡처링이다.

이 버튼에 등록된 이벤트는 다시 부모요소를 타고 window까지 올라가게 되는데 이 과정이 버블링이다.

이 두가지 작용 때문에 이벤트를 등록하고 실행하면 그 이벤트는 항상 두번 불려지게 된다.

우리는 버블링과 캡처링 중 한단계에만 이벤트를 등록할 수도 있다.

addEventListener로 event를 등록할때 3번째 인자로 boolean 값을 넣어줌으로써 event가 발생하는 시점을 조절할 수 있다.

//예시
addEventListener("click", fucntion(){console.log("Capturing")},true) --> 캡처링
addEventListener("click", fucntion(){console.log("Bubbling")},false) --> 버블링

버블링 막기

위 방법말고도 event가 버블링 되는 것을 막을 수 있는 방법이 있다.
funtion에 event를 받아오고 event에 stopPropagation()를 등록하면 된다.

addEventListener("click", (event) => stopBubbling(event))

funtion stopBubbling(event){
event.stopPropagation()
console.log("Now Bubbling stopped")

}

event.stopImmediatePropagation();
위 stopPropagation()과 비슷하나 같은 요소에 여러개의 이벤트를 등록했을때 사용한다.

이벤트 위임

버블링의 특징을 이용하여 다수의 요소에 event를 일일히 등록하는 것이 아닌 상위요소에만 등록하여 번거로움도 없애고 속도도 향상시키는 방법이다.

 <ul>
      <li>
        <h2>Item 1</h2>
        <p>Some text</p>
      </li>
      <li>
        <h2>Item 2</h2>
        <p>Some text</p>
      </li>
      .
      .
      .
    </ul>

여기서 li 요소를 클릭할 때 색깔이 바뀌는 기능을 넣고 싶다면 일반적으로

const listItems = document.querySelectorAll("li");

listItems.forEach((listItem) => {
  listItem.addEventListener("click", (e) => {
    e.target.classList.toggle("highlight");
  });
});

처럼 li 요소들에 각각 이벤트를 등록 할 수 있다. 하지만 이 방법은 js의 속도를 느리게 하는 원인이 될 수 있다.

이를 해결하기위해 event delegation 이벤트 위임을 사용하면 다음과 같다.

const list = document.querySelector("ul");

list.addEventListener("click", (e) => {
  e.target.closest("li").classList.toggle("highlight");
  form.click();
});

부모요소인 Ul에 이벤트를 등록하는데 가장 가까운 li요소의 색이 변하도록 하는 함수로 기능을 만들 수도 있는 것이다.

여기서 target과 currentTarget을 잘 보고 등록해야 원치 않는 동작을 막을 수 있다.

target : 이벤트가 발생한 요소를 반환
currentTarget: 이벤트를 등록해놓은 요소를 반환



이벤트 위임을 적절히 사용하는 것이 효율적인 코드를 작성하는 것이라 할 수 있다.

profile
프론트엔드 개발자입니다.

0개의 댓글