이벤트 버블링 (Event bubbling)

96Smilepeace·2023년 4월 15일
0

기술면접

목록 보기
1/3
post-thumbnail

🫧 이벤트 버블링 이란?

한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작합니다. 가장 최상단의 조상 요소를 만날 떄까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작합니다.

즉 발생한 요소의 이벤트가 더 상위 요소로 전달되어 가는 특성입니다.

HTML요소에 이벤트가 발생시 연쇄적 흐름이 일어나며 이러한 흐름을 이벤트 전파(Event Propagation)이라 하며 전파 방향에 따라 버블링과 캡처링으로 나뉜다.

여기서 상위 요소는 HTML DOM 트리 구조상으로 한 단계 위에 있는 요소를 상위 요소라고 합니다.

    <style>
      body * {
        margin: 10px;
        border: 1px solid red;
      }
    </style>
  </head>
  <body>
    <form onclick="alert('form')">
      form
      <div onclick="alert('div')">
        div
        <p onclick="alert('p')">p</p>
      </div>
    </form>
  </body>

해당 코드를 실행 시켜보면 다음과 같은 순서로 동작합니다.

  1. <p>태그의 할당된 onclick 핸들러가 동작합니다.

  2. <p>태그를 감싸고 있는 <div> 태그의 핸들러가 동작합니다.

  3. <div>를 감싸고 있는 <form> 태그의 핸들러가 동작합니다.

  4. document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작합니다.

    위의 순서대로 <p> -> <div> -> <form> 순서로 alert 창이 뜹니다.

이러한 흐름을 🫧 이벤트 버블링 이라고 부릅니다. 이벤트가 제일 깊은 곳에 있는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 모양이 마치 물속 거품(bubble)과 닮았기 떄문입니다.

대부분의 이벤트는 버블링 됩니다. 특정 이벤트를 제외하곤 대부분의 이벤트는 버블링 됩니다.


🚫 버블링 중단하기

🫧 이벤트 버블링은 타깃 이벤트에서 시작해서 <html> 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생합니다. 몇몇 이벤트는 window 객체까지 거슬러 올라가기도 합니다. 이 때도 모든 핸들러가 호출됩니다.

그런데 핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 명령할 수도 있습니다.

이벤트 객체의 메서드인 event.stopPropagation()를 사용하면 됩니다.

위 동일한 코드에서 <p>을 클릭해도 <div> <form> 핸들러는 동작하지 않습니다.

    <style>
      body * {
        margin: 10px;
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <form onclick="alert('form')">
      form
      <div onclick="alert('div')">
        div
        <p onclick="alert('p'); event.stopPropagation();">p</p>
      </div>
    </form>
  </body>

부모와 자식 둘다 이벤트를 등록한 상태에서 자식요소만 클릭했을때만 이벤트를 발생시키고 부모 요소에 할당된 이벤트를 발생시키고 싶지 않은 상황외 여러 상황이 있을것이다 브라우저 구조상 캡처링 - 버블링으로 동작하기 때문에 이벤트 동작 자체를 바꿀순 없지만 이벤트 전파를 방지 처리하는 메소드를 사용하여 해결하여야한다.

event.stopImmediatePropagation()
한 요소의 특정 이벤트를 처리하는 핸들러가 여러개인 상황에서, 핸들러 중 하나가 버블링을 멈추더라도 나머지 핸들러는 여전히 동작합니다.

event.stopPropagation()
위쪽으로 일어나는 버블링은 막아주지만, 다른 핸들러들이 동작하는 건 막지 못합니다.

event.stopImmediatePropagation()
버블링을 멈추고 요소에 할당된 특정 이벤트를 처리하는 핸들러 모두가 동작하지 않습니다.

e.preventDefault()
버블링을 멈추며 이벤트 자체 동작을 취소합니다.

이벤트 버블링을 막아야 하는 경우는 거의 없습니다, 자식 요소만 클릭하였다 하여도
다른시각으로 보면 부모요소도 클릭한 셈이 되어 구조적으로 옳기 떄문입니다,
버블링을 막아야 해결되는 문제라면 커스텀 이벤트 등을 사용해 문제를 해결할 수 있습니다.

🎯 Event.target

부모 요소 핸들러는 이벤트가 정확히 어디서 발생했는지 등에 대한 자세한 정보를 얻을 수 있습니다.

이벤트가 발생한 가장 안쪽의 요소는 타깃(target)요소라고 불리고, evnet.target 을 사용해 접근할 수 있습니다.

event.target 과 this (=event.currentTarget) 는 다음과 같은 차이점이 있습니다.

  • event.target 은 실제 이벤트가 시작된 "타깃"의 요소 입니다. 버블링이 진행되어도 변하지 않습니다.
  • this 는 "현재" 요소로, 현재 실행중인 핸들러가 할당된 요소를 참조합니다.

핸들러가 form.onclick하나 밖에 없더라도 핸들러 안의 모든 요소에서 발생하는 클릭 이벤트를 잡아내고(catch) 있습니다. 클릭 이벤트가 어디서 발생했든 상관없이 <form>요소까지 이벤트가 버블링 되어 핸들러를 실행시키기 때문입니다.

form.onclick 핸들러 내의 this 와 event.target 은 다음과 같이 확인해볼 수 있습니다.
  <body>
    <form id="form">
      form
      <div>
        div
        <p>p</p>
      </div>
    </form>
  <scirpt>
      form.onclick = function (event) {
  event.target.style.backgroundColor = "yellow";

  setTimeout(() => {
    alert("target = " + event.target.tagName + ", this=" + this.tagName);
    event.target.style.backgroundColor = "";
  }, 0);
};
   </script>
  </body>
  • this (event.currentTarget) - <form>요소에 있는 핸들러가 동작했기 떄문에 <form> 요소를 가르킵니다.

  • event.target - 폼 안쪽에 실제 클릭한 요소를 가리킵니다.

<form> 요소를 정확히 클릭했을 때는 event.target 과 this 가 같습니다.



이벤트 버블링 기능 참고 - CAPTAIN PANGYO
이벤트 버블링 기능 참고 - JAVASCRIPT.INFO
이벤트 버블링 기능 참고 - Inpa Dev

profile
🔥 노력천재

0개의 댓글