[JS] 이벤트 전파 / 이벤트 버블링 / 이벤트 캡처링

    반응형

    이벤트 전파 (Event Phase)

    브라우저에서 html 요소에 이벤트가 발생할 때, 이벤트가 전파되는 흐름에 따라 이벤트 버블링이벤트 캡처링이 발생함

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Event</title>
    </head>
    <body> body 영역
        <main> main 영역
            <div> div 영역
                <p> p 영역
                    <span>span 영역</span>
                </p>
            </div>
        </main>
    </body>
    </html>

     

    01) 이벤트 버블링 (Event Bubbling)

    이벤트 버블링은 이벤트 타깃 요소에서부터 최상위 요소인 html 문서까지 이벤트가 전파되는 것으로,

    addEventListener 이벤트는 기본적으로 버블링으로 동작함

    <script>
        const $body = document.querySelector('body');
        const $main = document.querySelector('main');
        const $div = document.querySelector('div');
        const $p = document.querySelector('p');
        const $span = document.querySelector('span');
    
        $span.addEventListener('click', function () {
            console.log('span 태그')
        });
        $p.addEventListener('click', function () {
            console.log('p 태그')
        });
        $div.addEventListener('click', function () {
            console.log('div 태그')
        });
        $main.addEventListener('click', function () {
            console.log('main 태그')
        });
        $body.addEventListener('click', function () {
            console.log('body 태그')
        });
    </script>

    span 태그를 클릭했을 때 consolg 창 (bubbling)

    • 위의 script 코드를 추가해서 console 창을 확인하면, span 태그를 클릭했을 때 span에서부터 body 태그까지 이벤트가 전파되는 과정을 확인할 수 있음

     

    02) 이벤트 캡처링 (Event Capturing)

    이벤트 캡처링은 최상위 요소(html)에서 해당 이벤트 타깃 요소까지 이벤트가 전파되는 것으로,

    addEventListener 이벤트에 true 값을 설정하여 캡처링으로 변경할 수 있음 (기본값 : false)

    <script>
        const $body = document.querySelector('body');
        const $main = document.querySelector('main');
        const $div = document.querySelector('div');
        const $p = document.querySelector('p');
        const $span = document.querySelector('span');
    
        // capturing
        $span.addEventListener('click', function () {
            console.log('capturing span 태그')
        }, true);
        $p.addEventListener('click', function () {
            console.log('capturing p 태그')
        }, true);
        $div.addEventListener('click', function () {
            console.log('capturing div 태그')
        }, true);
        $main.addEventListener('click', function () {
            console.log('capturing main 태그')
        }, true);
        $body.addEventListener('click', function () {
            console.log('capturing body 태그')
        }, true);
    </script>

    span 태그를 클릭했을 때 console 창 (capturing)

    • 이벤트 핸들러에 true 값을 추가하면, 최상위 요소부터 이벤트가 전파되는 것을 볼 수 있음

     

    03) Event.eventPhase

    eventPhase는 이벤트 핸들러에서 현재 평가 중인 이벤트 흐름 단계를 나타내는 것으로, 정수 값을 반환

    <script>
        const $body = document.querySelector('body');
        const $main = document.querySelector('main');
        const $div = document.querySelector('div');
        const $p = document.querySelector('p');
        const $span = document.querySelector('span');
    
        // capturing
        $span.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] capturing span 태그')
        }, true);
        $p.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] capturing p 태그')
        }, true);
        $div.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] capturing div 태그')
        }, true);
        $main.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] capturing main 태그')
        }, true);
        $body.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] capturing body 태그')
        }, true);
    
        // bubbling 
        $span.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] bubbling span 태그')
        });
        $p.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] bubbling p 태그')
        });
        $div.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] bubbling div 태그')
        });
        $main.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] bubbling main 태그')
        });
        $body.addEventListener('click', function () {
            console.log('['+ event.eventPhase + '] bubbling body 태그')
        });
    </script>

    span 태그를 클릭했을 때 console 창 (eventPhase)

    • 반환값이 1일 때 : 부모객체를 통해서 타켓 이벤트까지 전달한 경우
    • 반환값이 2일 때 :현재 타켓 이벤트인 경우
    • 반환값이 3일 때 : 타켓 이벤트에서 부모 객체로 전달한 경우

     

    04) 이벤트 방지

    이벤트를 차단하고 싶을 때 메서드를 사용하여, 이벤트를 막을 수 있음

     

    🔻stopPropagation() : 현재 이벤트가 발생한 요소에서 상위 요소로의 전파를 중단함

    <script>
        $span.addEventListener('click', function () {
            event.stopPropagation();
            console.log('['+ event.eventPhase + '] bubbling span 태그')
        });
    </script>

    span 태그를 클릭했을 때 console 창 (stopPropagation)

    • bubbling span 태그에서 이벤트가 중단되어 더 이상 실행하지 않음

     

    🔻preventDefault() : 해당 html 요소에 대한 기본 동작을 실행하지 않도록 지정

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Event</title>
    </head>
    <body>
        <a href="http://peazh.tistory.com">블로그 이동</a>
        <script>
            const $a = document.querySelector('a');
            $a.addEventListener('click', function () {
                event.preventDefault();
            })
        </script>
    </body>
    </html>
    • a 태그의 링크를 클릭했을 때, 원래는 페이지가 이동해야 하지만 메서드를 사용하여 이동하지 않음
    반응형

    댓글