본문 바로가기
Web/JAVASCRIPT

이벤트 버블링과 이벤트관련 함수들

by print_soo 2023. 7. 28.

이벤트 버블링이란? 

어떤 HTML 태그에 이벤트가 발생하면 그의 모든 상위요소까지 이벤트가 실행되는 현상을 말한다.

 

<div class="black-bg">
    <div class="white-bg">
        <h4>로그인하세요</h4>
        <div class="loginPage">
            
        </div>
    </div>
</div>

만약 위의 코드로 구성 되어 있는 웹 사이트에서 loginPage를 클릭하면 white-bg와 black-bg에 걸려있는 이벤트까지 작동 된다는 의미이다. 

 

따라서 이 이벤트 버블링을 막기 위해서는 이벤트 리스너 내부에서 쓰이는 함수 들에 대해서 알아야한다.

 

이벤트 리스너 내부에서 쓰이는 이벤트 함수들

document.querySelector('.black-bg').addEventListener('click', function(e){
  e.target;
  e.currentTarget;
  e.preventDefault();
  e.stopPropagation();
})

 

이벤트 리스너 내부에서 이벤트 함수를 쓰기 위해서는 함수의 매개변수에 e를 작성해야한다.

 

  • e.target
    • 실제 클릭한 요소를 알려준다.( 이벤트가 발생한 곳 )
  • e.currentTarget
    • 지금 이벤트 리스너가 달린 곳을 알려준다. ( this라고 써도 똑같다.)
  • e.preventDefault()
    • 실행하면 이벤트 기본 동작을 막아준다.
  • e.stopPropagation()
    • 실행하면 내 상위요소로의 이벤트 버블링을 중단해준다.

적용 해보기 

<div class="black-bg">
    <div class="white-bg">
        <h4>로그인하세요</h4>
        <form action="success.html">
            <div class="my-3">
                <input type="text" class="form-control" name="id">
            </div>
            <p id="error-id">아이디가 입력되지 않았습니다.</p>
            <div class="my-3">
                <input type="password" class="form-control" name="password">
            </div>
            <p id="error-password">비밀번호가 입력되지 않았습니다.</p>
            <button type="submit" id="submit" class="btn btn-primary">로그인</button>
            <button type="button" class="btn btn-danger" id="close">취소</button>
        </form>
    </div>
</div>

<!------------------------------------------------------------------>

<div class="main-bg">
    <h4>Shirts on sale</h4>
    <button id="login" class="btn btn-danger">로그인</button>
</div>

 

위의 화면에서 불투명한 검은색 화면을 누르면 모달 창을 사라지게 하고 싶어서 아래의 코드를 작성했다. 

 

 

$('.black-bg').on('click', function(e){ 
    $('.black-bg').removeClass('show-modal');
})

 

black-bg를 누르면 모달 창이 사라지긴 했지만 다른 텍스트 입련이나 흰 배경의 모달창을 눌러도 모달창이 사라지는 오류가 발생했다. 

 

이 오류가 발생한 이유는 아까 배운 이벤트 버블링 때문이다.

text를 눌러도 상위요소인 black-bg까지 이벤트 버블링이 일어나 black-bg를 누른 것과 같은 효과를 나타낸다. 따라서 해당 오류를 해결하려면 이벤트 함수를 사용해야한다.

 

따라서 아래의 로직을 따르면 된다.

1. black-bg가 눌린다면 아래의 로직이 작동한다.
2. 실제로 클릭한 요소가 black-bg인 경우에만 모달창이 사라지게 한다.

 

 

$('.black-bg').on('click', function(e){
            
    if (e.target == document.querySelector('.black-bg'){
        $('.black-bg').removeClass('show-modal');
    }

})

 

 

만약에 jquery를 이용해서 조건문을 작성한다면 아래와 같이 작성해야한다. 

// 성릴 안됨 X

$('.black-bg').on('click', function(e){
            
    if (e.target == $('.black-bg')){
        $('.black-bg').removeClass('show-modal');
    }

})

// 성립 됨 O

$('.black-bg').on('click', function(e){
            
    if ($(e.target) == $('.black-bg')){
        $('.black-bg').removeClass('show-modal');
    }

})

 


적용 해보기 2 - 이벤트 리스너 줄여보기

이전에 우리는 탭 기능을 만들었고 이 탭 기능을 구현하기 위해서는 아래의 코드와 같이 3개의 list에 각각 이벤트 리스너를 달아서 사용했다.  이렇게 이벤트 리스너를 많이 달면 램 용량을 잡아먹어 성능상 좋지 않은 결과를 만들어 낼 수 있다. 

 

따라서 이벤트 버블링을 통해서 이벤트 리스너를 줄여보자.

 

// 3개의 이벤트 리스너 사용 + 함수로 축약
for (let i = 0; i < 3; i++) {
    tab_button.eq(i).on('click', function () {
        openTab(i)
    });
}

function openTab(i){
    tab_button.removeClass('orange');
    tab_button.eq(i).addClass('orange');
    tab_content.removeClass('show');
    tab_content.eq(i).addClass('show');
}

 

 

탭 버튼 HTML을 잘 보면 탭 버튼 상위요소에는 ul 태그가 있다.

<ul class="list">
    <li class="tab-button">Products</li>
    <li class="tab-button">Information</li>
    <li class="tab-button">Shipping</li>
</ul>

 

즉, 이벤트 버블링 현상으로 인하여 탭 버튼을 클릭했을 때 ul 태그에 있는 이벤트까지 실행되므로 ul 태그에 이벤트 리스너를 달아 놓으면 3개의 버튼 모두 관리가 가능해진다.

 

$('.list').click(function(e){
    if (e.target == document.querySelectorAll('.tab-button')[0]){
        openTab(0)
    } else if (e.target == document.querySelectorAll('.tab-button')[1]) {
        openTab(1)
    } else {
        openTab(2)
    }
})

function openTab(i){
    tab_button.removeClass('orange');
    tab_button.eq(i).addClass('orange');
    tab_content.removeClass('show');
    tab_content.eq(i).addClass('show');
}

 

따라서 위와 같이 list가 클릭되었을 때 e.target으로 어떤 버튼이 눌러졌는지 확인후 해당 버튼에 맞는 내용을 출력시킬 수 있다.

 

dataset으로 축약시키기

HTML

<!-- 기존 -->

<div class="container mt-5">
    <ul class="list">
        <li class="tab-button">Products</li>
        <li class="tab-button">Information</li>
        <li class="tab-button">Shipping</li>
    </ul>
    <div class="tab-content">
        <p>상품설명입니다. Product</p>
    </div>
    <div class="tab-content">
        <p>스펙설명입니다. Information</p>
    </div>
    <div class="tab-content">
        <p>배송정보입니다. Shipping</p>
    </div>
</div>

<!-- 변경 -->

<div class="container mt-5">
    <ul class="list">
        <li class="tab-button" data-id="0">Products</li>
        <li class="tab-button" data-id="1">Information</li>
        <li class="tab-button" data-id="2">Shipping</li>
    </ul>
    <div class="tab-content">
        <p>상품설명입니다. Product</p>
    </div>
    <div class="tab-content">
        <p>스펙설명입니다. Information</p>
    </div>
    <div class="tab-content">
        <p>배송정보입니다. Shipping</p>
    </div>
</div>

 

JS

// 기존
$('.list').click(function(e){
    if (e.target == document.querySelector('.tab-button')[0]){
        openTab(0)
    } else if (e.target == document.querySelector('.tab-button')[1]) {
        openTab(1)
    } else {
        openTab(2)
    }
})

// 변경
$('.list').click(function(e){
    openTab(Number(e.target.dataset.id))
})

 

 

 

 

 

 

[결론]
.
.
1. 이벤트 버블링은 항상 일어난다.
2. 이벤트 관련 유용한 함수들을 사용할 수 있다.
3. 이벤트 버블링을 알면 이벤트 리스너를 줄일 수 있다.

.
.