본문 바로가기

Frontend/JavaScript

preventDefault 와 stopPropagation 차이점 (+ 이벤트 버블링, 캡쳐링)

 

preventDefault()

기본동작 취소

예를 들어 버튼의 submit 은 기본적으로 값을 전송하고, 새로고침 하는 기능을 한다.

이때 e.preventDefault() 를 사용하면 submit의 전송과 새로고침을 막는다.

또 다른 예로, 기본적으로 실행되는 a 태그의 링크이동을 막는다.

 

stopPropagation()

이벤트 전파 중지 (기본동작을 막지는 않음)

버블링과 캡쳐링을 막는 역할을 한다 

👩🏻‍💻 버블링, 캡쳐링이 뭔지 알아보자


버블링

설정없이 기본적으로 버블링으로 동작

자식 요소를 누르면 한단계씩 타고 올라가서 자신을 감싸고 있는 최상위 부모요소에 걸린 이벤트까지 실행되는 것

 

아래 예제코드의 경우 inner를 클릭하면 Inner => Middle => Outer 순으로 alert이 실행된다. [자식에서 부모로 타고 올라감] 

❓ middle을 클릭하면? Inner => Middle 순으로 alert이 실행된다.

❓ outer를 클릭하면? Outer 만 실행된다.

  <div class="outer">
    Outer
    <div class="middle">
      Middle
      <div class="inner">
        Inner
      </div>
    </div>
  </div>
document.querySelector('.outer').addEventListener('click', (event) => {
  alert('Outer');
}, false); // false는 버블링 단계

document.querySelector('.middle').addEventListener('click', (event) => {
  alert('Middle');
}, false);

document.querySelector('.inner').addEventListener('click', (event) => {
  alert('Inner');
}, false);

이렇게 addEventListener 인자에 false를 넣으면 버블링으로 동작되고, 아무 인자도 안 넣으면 기본적으로 버블링으로 동작함

 

캡쳐링

옵션으로 설정 (이벤트리스너 마지막 인자에 true를 넣으면 캡쳐링으로 동작함)

자식요소를 클릭하면 부모요소에서 자식요소로 이벤트가 전파되는 것

 

아래 예제코드에서 inner를 클릭시 Outer => Middle => Inner 순으로 alert이 실행된다. [부모에서 자식으로 타고 내려옴] 

❓ middle을 클릭하면? Middle => Inner 순으로 alert이 실행된다.

❓ outer를 클릭하면? Outer 만 실행된다.

  <div class="outer">
    Outer
    <div class="middle">
      Middle
      <div class="inner">
        Inner
      </div>
    </div>
  </div>
// 캡처링 단계
document.querySelector('.outer').addEventListener('click', (event) => {
  alert('Outer');
}, true); // true는 캡처링 단계

document.querySelector('.middle').addEventListener('click', (event) => {
  alert('Middle');
}, true);

document.querySelector('.inner').addEventListener('click', (event) => {
  alert('Inner');
}, true);

 


e.stopPropagation 예제코드

: 이벤트 버블링, 캡쳐링 막기위해 사용

최하위 요소에 stopPropagation 을 걸어주면 상위요소까지 전파되는 이벤트를 중단시켜줌

// 이벤트 전파 중단
document.querySelector('.inner').addEventListener('click', (event) => {
  event.stopPropagation(); // 이후 단계로 전파 중단
  alert('Inner propagation stopped!');
}, false);

false니까 버블링이고, 버블링이 기본 동작이기 때문에 false는 생략가능.

위 코드는 alert('Inner propagation stopped!') 만 실행됨. (기존에 버블링으로 전파됐던 Middle, Outer 이벤트는 실행되지 않음)

이제 inner를 클릭하면 Inner => Middle => Outer 순으로 alert이 실행되는 게 아니라 Inner 에 걸린 이벤트 리스너만 실행됨