이벤트 버블링이란?
어떤 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. 이벤트 버블링을 알면 이벤트 리스너를 줄일 수 있다.
.
.
'Web > JAVASCRIPT' 카테고리의 다른 글
Array 와 Object (0) | 2023.07.31 |
---|---|
dataset (0) | 2023.07.30 |
탭기능 만들며 배우는 for 반복문 (0) | 2023.07.27 |
JS 파일을 따로 선언했는데 실행이 되지 않는 경우 (0) | 2023.07.27 |
브라우저에서 끝까지 스크롤 했다는 것을 확인하기 (0) | 2023.07.26 |