ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 - 이벤트 버블링과 캡쳐링
    프론트엔드/JavaScript 2020. 10. 20. 10:37

    자바스크립트에서 이벤트를 실행하면 버블링과 캡쳐링이란 것을 발생하게 할 수 있다.

     

    간단하게 말하자면 이벤트가 발생 시 HTML 문서 구조상 이벤트가 다른 문서로 전이되는 것을 말한다.

     

    코드를 살펴보자.

    1. 캡쳐링과 버블링

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body id="body">
        <div id="div">
            <p id="p">
                <button id="btn"> 캡쳐링과 버블링 </button>
            </p>
        </div>
    </body>
    <script>
        let button = document.getElementById("btn");
        let p = document.getElementById('p');
        let div = document.getElementById('div');
        let body = document.getElementById('body');
    
        function ftest(){
            console.log("일어난 이벤트: "+event.target.nodeName+" 이벤트가 일어나는 현재 노드: "+this.nodeName);
        }
    
        btn.addEventListener('click', ftest, true);
        p.addEventListener('click', ftest, true);
        div.addEventListener('click', ftest, true);
        body.addEventListener('click', ftest, true);
    
    </script>
    </html>

     

    위 코드를 살펴보자.

     

    대략 그림으로 위 HTML문서의 구조를 나타내면 다음과 같다.

     

     

    이때 여기서 버튼을 누르면 어떤 결과가 나올까?

     

    다음과 같은 결과가 나온다.

     

    버튼은 한번만 눌렀는데 결과값은 4개가 나온 것이다.

     

    HTML 문서의 각 노드들은 어딘가 종속되어있는 계층적 구조로 이뤄진다.

     

    그래서 어느 한 곳에서 이벤트가 발생하면 다른 곳으로 이벤트가 전파된다.

     

    그리고 이때 이 이벤트가 전파되는 방향에 따라 이것을 캡쳐링과 버블링이라고 부르는 것이다.

     

    둘은 구분하면 다음과 같다.

     

    캡쳐링: 자식 요소에서 발생한 이벤트가 부모 요소에서 시작해 이벤트가 발생한 자식 요소까지 도달하는 것

    버블링: 자식 요소에서 발생한 이벤트가 부모 요소로 전파되는 것

     

    그림으로 나타내면 다음과 같다.

     

     

    위 코드는 캡쳐링을 나타내는 코드로서 실행 결과는 다음과 같다.

     

    캡쳐링은 아래와 같이 <body> - <div> - <p> - <button> 순으로 이벤트가 실행된다.

     

     

    버블링 코드는 아래와 같다.

     

    둘의 차이는 addEventListener 메서드를 실행할 때 3번째 파라미터 값으로 true/false 중 어떤 것을 주느냐의 차이다.

     

    참고로 false가 디폴트값이고 이는 버블링을 나타낸다.

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body id="body">
        <div id="div">
            <p id="p">
                <button id="btn"> 캡쳐링과 버블링 </button>
            </p>
        </div>
    </body>
    <script>
        let button = document.getElementById("btn");
        let p = document.getElementById('p');
        let div = document.getElementById('div');
        let body = document.getElementById('body');
    
        function ftest(){
            console.log("버블링:" + " 일어난 이벤트: "+event.target.nodeName+" 이벤트가 일어나는 현재 노드: "+this.nodeName);
        }
    
        btn.addEventListener('click', ftest, false);
        p.addEventListener('click', ftest, false);
        div.addEventListener('click', ftest, false);
        body.addEventListener('click', ftest, false);
    
    </script>
    </html>

     

    버블링은 아래와 같이 <button> - <p> - <div> - <body> 순으로 이벤트가 실행된다.

     

    2. 버블링과 캡쳐링 중단시키기

    버블링, 캡쳐링은 HTML 구조상 자연스럽게 생기는 이벤트의 전파다.

     

    그러나 이벤트 진행상 버블링이나 캡쳐링을 중단해야할 상황도 있다.

     

    그럴 때는 'stopPropagation()' 메서드를 사용하면 된다.

     

    이 때 'stopPropagation' 메서드는 'event' 객체를 이용해서 호출해주면 된다.

     

    참고로 'event' 객체란 이벤트 핸들러를 이용해서 이벤트 코드를 실행할 때 해당 핸들러에 전달되는 객체다.

     

    이 'event' 객체를 이용하면 이벤트와 관련된 다양한 사항을 제어할 수 있다.

     

    코드는 다음과 같다.

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body id="body">
        <div id="div">
            <p id="p">
                <button id="btn"> 캡쳐링과 버블링 </button>
            </p>
        </div>
    </body>
    <script>
        let button = document.getElementById("btn");
        let p = document.getElementById('p');
        let div = document.getElementById('div');
        let body = document.getElementById('body');
    
        function ftest(){
            console.log("버블링:" + " 일어난 이벤트: "+event.target.nodeName+" 이벤트가 일어나는 현재 노드: "+this.nodeName);
        }
        function stest(){
            console.log("버블링:" + " 일어난 이벤트: "+event.target.nodeName+" 이벤트가 일어나는 현재 노드: "+this.nodeName);
            event.stopPropagation();
        }
    
        btn.addEventListener('click', ftest, false);
        p.addEventListener('click', ftest, false);
        div.addEventListener('click', stest, false);
        body.addEventListener('click', ftest, false);
    
    </script>
    </html>

     

    'stopPropagation'메서드가 추가된 메서드를 하나 더 만들어줘서 div 단계에서 버블링이 중단되게 했다.

     

     

    실행 결과는 다음과 같다.

     

    위 코드대로 'stopPropagation()' 메서드가 실행되는 <div> 태그까지만 이벤트가 실행되었다.

Designed by Tistory.