> 기초/Javascript

TIL-2024.03.19 - JS - 이벤트 버블링 & 캡처링

Janku 2024. 3. 19. 20:57

 

 

 

목표: 

  1. 이벤트 캡처링
  2. 이벤트 버블링 
  3. 이벤트 캡처링과 버블링 막는 방법

 

이벤트 캡처링(Event Capturing):

  • 캡처링은 이벤트가 DOM 트리의 상위 요소에서 하위 요소로 향하는 단계 (상위 > 하위)
  • 이벤트가 발생한 요소의 부모 요소부터 시작하여 해당 요소의 가장 최상위 요소인 document까지 이벤트가 전파.
  • 예를 들어, 버튼 요소를 클릭하면, 이 클릭 이벤트는 가장 상위 요소인 document까지 전파되는데, 이 단계에서 이벤트는 이벤트 리스너에 의해 캡처링 단계에서 포착될 수 있습니다.
// index.html
<div id="outer">
    <div id="inner">
        <button id="button">Click me</button>
    </div>
</div>

// main.js
document.getElementById('outer').addEventListener('click', function(){
    console.log('캡처링 단계: Outer div');
}, true);

document.getElementById('inner').addEventListener('click', function(){
    console.log('캡처링 단계: Inner div');
}, true);

document.getElementById('button').addEventListener('click', function(){
    console.log('캡처링 단계: Button');
}, true);


// 캡처링 단계: Outer div
// 캡처링 단계: Inner div
// 캡처링 단계: Button

 

 

 

이벤트 버블링(Event Bubbling):

  • 버블링은 이벤트가 발생한 요소에서 상위 요소로 향하는 단계. (하위 > 상위) 
  • 캡처링과 반대로, 이벤트가 가장 하위 요소에서 시작하여 부모 요소로 이동.
  • 캡처링 단계 이후에 발생하며, 이벤트가 발생한 요소를 포함한 모든 부모 요소까지 이벤트가 전파.

 

// index.html
<div id="outer">
    <div id="inner">
        <button id="button">Click me</button>
    </div>
</div>

// main.js
document.getElementById('outer').addEventListener('click', function(){
    console.log('캡처링 단계: Outer div');
}, true);

document.getElementById('inner').addEventListener('click', function(){
    console.log('캡처링 단계: Inner div');
}, true);

document.getElementById('button').addEventListener('click', function(){
    console.log('캡처링 단계: Button');
}, true);

document.getElementById('outer').addEventListener('click', function(){
    console.log('버블링 단계: Outer div');
});

document.getElementById('inner').addEventListener('click', function(){
    console.log('버블링 단계: Inner div');
});

document.getElementById('button').addEventListener('click', function(){
    console.log('버블링 단계: Button');
});


캡처링 단계: Outer div
캡처링 단계: Inner div
캡처링 단계: Button
버블링 단계: Button
버블링 단계: Inner div
버블링 단계: Outer div

 

 

 

 

이벤트 캡처링과 버블링 막는 방법:

 

 

 

1. preventDefault() 메서드 사용 > 기본 동작을 취소하는 데 사용

... 중략 ...
  <body>
    <div>
      <a href="https://naver.com" id="naver-link">네이버</a>
    </div>
  </body>
  <script>
    document.querySelector("#naver-link").addEventListener("click", (e) => {
      e.preventDefault(); 
      console.log("preventDefault로 네이버로 이동안하고 console 만 찍어줌!")
    });
  </script>
  
  ... 중략 ...

 

 

 

 

2. stopPropagation() 메서드 사용 > 상위 요소가 이벤트를 감지할 수 없고 이벤트리스너가 가르키고 있는 요소만 이벤트를 감지

... 중략 ...

  <body>
    <div class="div-container">
      <div class="div-button" style="cursor: pointer">날 눌러보소</div>
    </div>
  </body>
  <script>
    document.querySelector(".div-button").addEventListener("click", (e) => {
      alert(".div-button 클릭!");
    });

    document.querySelector(".div-container").addEventListener("click", (e) => {
      alert("body 클릭!");
    });
  </script>
  
  ... 중략 ...

 

1. 위의 예제에서 .div-container .div-button 에 각각 click 이벤트 리스너를 할당

2. 날 눌러보소 라는 div tag 클릭한 경우, 아래의 두장의 사진과 같이 이벤트 버블링이 발생해서 두개의 alert 문 실행

 

 

3. 아래의 코드와 같이 e.stopPropagation() 을 사용하면, 해당 요소의 이벤트만 감지

 

    document.querySelector(".div-button").addEventListener("click", (e) => {
      e.stopPropagation();
      alert(".div-button 클릭!");
    });

    document.querySelector(".div-container").addEventListener("click", (e) => {
      e.stopPropagation();
      alert("body 클릭!");
    });

 

 

 

3. 캡처링에서만 막기:

document.getElementById('button').addEventListener('click', function(event){
    event.stopPropagation(); // 버블링을 막음
}, true);


// addEventListener의 세 번째 매개변수를 true로 설정하여 이벤트 캡처링 단계에서만 동작하도록 만들고, 그 안에서 stopPropagation()을 호출합니다.