이벤트 버블링

조 은길·2022년 6월 4일
0
post-thumbnail
post-custom-banner
  • 한 눈에 보는 이벤트 버블링과 캡쳐링 흐름도


들어가기 앞서

모달창의 검은 배경을 누르면 모달창이 닫히는 기능을 추가해보았다.

<div class="black-bg">
  <div class="white-bg">
    모달창 내용
  </div>
</div>

▲ 모달창 HTML은 대충 이런 식으로 코드가 짜여있고

모달창 오픈할 때 show-modal 클래스명을 넣어서 오픈했다면


document.querySelector('.black-bg').addEventListener('click', function(){
  document.querySelector('.black-bg').classList.remove('show-modal');
})

이렇게 코드짜면 될듯요

그럼 검은 배경 눌렀을 때 모달창이 잘 닫힙니다.

근데 이상한 점이 하나 있습니다.

검은배경 뿐만 아니라 흰배경, input, 글자 등 모달창 내부의 어떤걸 눌러도 다 닫힙니다.

뭔가 이상한듯!!


이벤트 버블링

어떤 HTML 태그에 이벤트가 발생하면 그의 모든 상위요소까지 이벤트가 실행되는 현상을 이벤트 버블링이라고 합니다.

click이라는 이벤트로 예를 들어보면,

HTML 태그에 클릭이 발생하면 그의 모든 상위요소까지 자동으로 클릭된다는 말입니다.


<div>
  <div>
    <p>안녕</p>
  </div>
</div>

▲위의 코드에서 p태그 안녕이라는 글자를 클릭하면 브라우저는 사용자가 클릭을 총 3번 했다고 인지합니다.

p랑 그 위의 div랑 그 위의 div랑 이렇게요.

이게 이벤트 버블링인데 브라우저는 원래 그렇게 동작하도록 되어있습니다.

이 사실을 모르고 코드짜다보면 가끔 이상한 현상이 발생할 수도 있습니다.


그래서 아까 "검은배경 누르면 모달창 닫아주세요~" 코드를 다시 살펴보면

왜 흰배경 눌러도 모달창이 닫히냐면


<div class="black-bg"> (← 이거 누르면 모달창 닫으라고 코드짰음)
  <div class="white-bg">
    모달창 내용
  </div>
</div>

유저가 <div class="white-bg"> 이거 클릭해도

이벤트 버블링 때문에 <div class="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() 실행하면 내 상위요소로의 이벤트 버블링을 중단해줌

몇개만 뽑아봤는데 필요할 때 가져다가 쓰면 됩니다.

e.target 이런거 출력해보십쇼 진짜 그게 맞나

여기서 중요한건 e.target인데

이벤트 버블링이 일어난다고 해도,
사용자가 실제로 클릭한 그 요소는 저 문법으로 찾아낼 수 있다는걸 기억해둡시다.


그럼 모달창 닫기 버그를 해결해봅시다

코드를 대충 이렇게 수정하면 되지 않을까요?

document.querySelector('.black-bg').addEventListener('click', function(e){
  if (지금 실제로 클릭한거 == 검은 배경) {
    document.querySelector('.black-bg').classList.remove('show-modal');
  }
})
  • (참고)

저기서 e.currentTarget 출력해보면 검은배경이 나오기 때문에

e.target == e.currentTarget 이렇게 써도 될듯요

아니면 e.target == this 이렇게 써도 될듯요

  • (참고2)

jQuery 셀렉터로 찾은 결과와

querySelector 셀렉터로 찾은 결과는 다르게 생겼습니다.

출력해보면 전자는 이상한 object 이런게 나오고 후자는 <html> 이런게 나옵니다.

그래서 e.target == $('.black-bg') 이건 사용불가능합니다.

그리고 애초에 jQuery 셀렉터끼리 등호비교는 불가능합니다.

$('.black-bg').is($('.black-bg')) 이런 비교용 함수쓰든가 하면 됩니다.

위 예제에선 $(e.target).is($('.black-bg')) 이러면 됩니다.


오늘의 결론

  1. 이벤트 버블링은 항상 일어난다

  2. 이벤트 관련 유용한 함수들을 사용가능하다

잘 기억해두면 됩니다.

profile
좋은 길로만 가는 "조은길"입니다😁
post-custom-banner

0개의 댓글