JavaScript

| JavaScript | 'DOM' preventDefault() 마우스 우클릭 제한, stopPropagation() 이벤트 전파 막기

데브빈 2022. 5. 18. 21:18

preventDefault()

브라우저의 기본 이벤트 동작을 취소한다. (하지만 이벤트 전파는 못 막음)

브라우저는 HTML 태그를 통해 여러가지 기능들을 제공하지만, 때때로 그러한 기능이 방해가 되는 경우가 있다.

<!-- 앵커의 기본 동작을 중지 -->
<a href="https://www.naver.com" class="link">네이버 링크입니다만..</a>
<script>
    const link = document.querySelector('.link');
    link.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>

<!-- submit 의 기본 동작을 중지 -->
<form action="">
    <button type="submit" class="submit">제출</button>
</form>
<script>
    const submit = document.querySelector('.submit');
    submit.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>

<마우스 우클릭 제한: 경고창 띄우기>

이벤트 타입: 'contextmenu'

window.addEventListener('contextmenu', (event) =>{
            event.preventDefault();
            alert("다 보고 있어염!");
});

stopPropagation()

부모로부터의 이벤트 전파를 stop하는 것이다. 

 

< 어디 콘솔부터 찍힐까? >

  <body>
    <form action="">
      <button type="submit" class="submit">제출</button>
    </form>

    <script>
      const submit = document.querySelector(".submit");
      submit.addEventListener("click", (event) => {
        console.log("clicked");
        event.preventDefault();
        // 이벤트 전파를 막고 싶다면
        // event.stopPropagation();
      });

      document.body.addEventListener("click", () => {
        console.log("event still alive!");
      });
    </script>
  </body>
</html>

 

답: ‘clicked’부터 찍힘. 

기본값인 버블링이벤트라서 밑에서 루트까지 타고 올라가면서 이벤트 전파.

1. 이벤트 전파를 막고 싶다면 stopPropagetion 주석을 풀어보면  

 2. 세번째 인자값의 true값을 주면 캡처링을 볼 수 있다.!!

 

body에 있는 이벤트리스너가 캡쳐링이벤트이기 때문에 stopPtopagation을 사용했다해도 이미 이벤트(console.log(‘event still alive!’)가 끝나있다. 

 

< 부모 자식 간에 각각 다른 이벤트리스너가 부여됐을 때 이벤트 흐름에 주의하기>

  1. P 태그를 클릭하면 p 태그의 컨텐츠를 출력하는 alert 창을 띄워주고
  2. 삭제 버튼을 클릭하면 삭제할 것인지를 물어보는 confirm 창을 띄워주고, 확인을 누르면 P태그를 삭제합니다.
    <h1>나의 todo list</h1>
    <p>
      1. 오늘 저녁에는 부대찌게를 끓여 먹겠다. 
      <button type="button">삭제</button>
    </p>
    <p>2. 후식으로 슈팅스타를 먹겠다.
    <button type="button">삭제</button>
    </p>
    <p>
      3. 자기 전에 반드시 내일 아침 메뉴를 생각해두겠다.
      <button type="button">삭제</button>
    </p>

    <script>
      const txts = document.querySelectorAll("p");
      const btns = document.querySelectorAll("button");

       for (let i = 0; i < txts.length; i++) {
           txts[i].addEventListener('click', (event) => {
              // alert(event.target.textContent.slice(0, -2));
              alert(event.target.firstChild.textContent);
          })
      }

      // txts 유사배열인 노드리스트라 포이치는 IE불가능
      //  Array.prototype.forEach.call(txts, (item) => {
      //   item.addEventListener("click", (event) => {
      //     // alert(event.target.textContent.slice(0, -2));
      //     alert(event.target.firstChild.textContent);
      //   });
      // });

      // 삭제하면 또 창이 오는 것은 버블링..
      // 이벤트 버블링으로 부모요소에 있는 p태그의 alert이벤트가 실행되어 버려서!
      // 이걸 막기위해서 stopPropagation 쓰는 것
      for (const item of btns) {
        item.addEventListener("click", (event) => {
          let result = confirm("삭제하시겠습니까?");
          event.stopPropagation();
          if (result) {
            item.parentElement.remove();
          }
        });
      }

 

👉 alrt 창에서 삭제 텍스트 지우기 3가지 방법! 

  1. alert(event.target.textContent.slice(0, -2));     // pritter 사용시 적용 안됨
  2. alert(event.target.firstChild.textContent);
  3. alert(this.textContent.replace(this.firstElementChild.textContent, ""));

👉 cofirm 창에서 확인을 누르면 삭제가 또 나오는 경우 

이벤트 버블링으로 부모요소에 있는 p태그의 alert이벤트가 실행되기 때문이다. 

이걸 막기위해  event.stopPropagation(); 써주면 된다. 

 

👉 txt에는 p태그의 노드리스트가 들어가있어서 remove를 바로 써줄 수 없다!

 

 

하지만 이 문제는 이벤트 전파없이 if문안에 이벤트 위임을 통해 구현할 수 있다.,,!!