[JS] 이벤트 흐름 / 이벤트 위임

은채·2022년 9월 16일
0

JavaScript

목록 보기
25/26
post-thumbnail

이벤트 흐름

브라우저가 사용자의 입력을 받았을 때

브라우저 화면에서 이벤트 발생

  • 이벤트 : 마우스 클릭, 휠 움직임, 마우스 포인터 이동, 화면 터치 등 모든 종류의 사용자 제스처

이벤트 대상 찾기

  • 이벤트가 발생한 좌표에 무엇이 있는지 확인
  • 렌더링 과정 중의 '페인트 기록'을 찾는다.

캡처링 단계

  • 페인트 기록을 통해 좌표를 알아냈다면
  • 해당 좌표에 위치한 요소의 이벤트 리스너를 실행
  • 이 과정이 캡쳐링 단계 (capturing phasese)

  • 이 때 타켓 요소의 가장 최상위 window 객체로부터 캡처링 단계의 이벤트 리스너가 등록이 되어있는 지 확인
  • 있다면 실행
  • 계속 자식 요소로 전파되며 만나는 캡쳐링 이벤트 리스너 실행
  • 타켓 요소까지 이동

버블링 단계

  • 캡쳐링이 끝나고, 최초에 이벤트가 발생했던 요소에 버블링 이벤트 리스너가 있다면 실행
  • 다음 직계 부모 요소에 버블링 이벤트 리스너가 있다면 실행
  • 가장 최상위 window 객체까지 계속 전파
<!DOCTYPE html>
<html>
  <head>
    <title>이벤트 캡쳐링, 버블링</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button type="button">click</button>

    <script>
      window.addEventListener(
        "click",
        function () {
          console.log(1);
        },
        useCapture
      );

      document.addEventListener(
        "click",
        function () {
          console.log(2);
        },
        true
      );

      document.documentElement.addEventListener(
        "click",
        function () {
          console.log(3);
        },
        true
      );

      document.body.addEventListener(
        "click",
        function () {
          console.log(4);
        },
        true
      );

      document.querySelector("button").addEventListener(
        "click",
        function () {
          console.log(5);
        },
        true
      );

      document.querySelector("button").addEventListener(
        "click",
        function () {
          console.log(6);
        },
        false
      );

      document.body.addEventListener(
        "click",
        function () {
          console.log(7);
        },
        false
      );

      document.documentElement.addEventListener(
        "click",
        function () {
          console.log(8);
        },
        false
      );

      document.addEventListener(
        "click",
        function () {
          console.log(9);
        },
        false
      );

      window.addEventListener(
        "click",
        function () {
          console.log(10);
        },
        false
      );
    </script>
  </body>
</html>

캡쳐링 단계

  1. 윈도우 객체
  2. document
  3. document의 documentElement(html요소)
  4. body
  5. button ( 타깃요소 )

버블링 단계

  1. button ( 타깃요소 )
  2. body
  3. document의 documentElement(html요소)
  4. document
  5. 윈도우 객체
  • addEventListner ("이벤트 타입", 이벤트 발생 시 실행할 함수, useCapture => 캡쳐링 단계에서 해당 리스너를 실행 여부 T/F)

  • 버튼 클릭 했을 때 : 캡쳐링 -> 버블링 실행

  • 버튼 바깥을 클릭했을 때 : 5, 6번 실행되지 않음

이벤트 위임

  • 이벤트 리스너가 div 요소에 있고 사용자가 부모 요소 div의 자식인 button 태그를 클릭했다면?

    • 브라우저는 이벤트가 발생한 button 태그를 찾는다
    • 이벤트 캡쳐링, 버블링을 통해 button 태그의 부모 요소인 div의 이벤트 리스너를 실행한다

event 객체 = 돔에서 일어나는 이벤트의 정보 포함

  • event.currentTarget은 이벤트가 등록된 요소
  • 이벤트 리스너 안의 this 가 참조하는 대상과 같음
  • 이벤트가 최초에 발생한 요소는 event.target에 참조

확인해보기

  • 버튼을 누르면?
    • this = event.currentTarget
    • event.target = 이벤트가 최초에 발생한 button

또 확인해보기

  • 버튼을 눌렀을 때, 아이템을 만들건데 이벤트는 더 상단의 div에 있을 때.

    • 이벤트 리스너는 div를 클릭 할 때로 만들었음
    • event.target의 태그 이름이 button 이면, li태그를 만들어서 ul안에 배치
  • 버튼을 누르면 새로운 li들이 생겨난다.

  • li들을 눌렀을 때 console.log 찍히게 이벤트 발생시키기도 추가

  • 기존에 있던 아이템, 새로 생긴 hello~들을 누르면 hit 이 콘솔에 나온다.

  • 버튼, li, 새로 생긴 자식 요소 들에도 모두 이벤트가 등록되었다.

이벤트 위임

  • 이벤트를 발생시키고 싶은 요소를 이벤트 리스너가 설치된 부모 요소의 자식으로 배치한다면
    • 그 요소가 몇 개든 상관없이 이벤트 등록 가능
    • 요소가 동적으로 생성되어 계속 추가되어도 같은 기능 유지
  • 이벤트 위임 : 이벤트 흐름을 활용하여 단일의 이벤트 리스너가 여러개의 이벤트 대상을 처리할 수 있게 되는 방법
profile
반반무마니

0개의 댓글