• Blog
  • Projects
  • Resume
profile_image

[JavaScript] DOM 이벤트 플로우 (캡쳐링, 버블링)

JavaScriptDOM

2021.02.16

1. DOM의 이벤트 플로우 (click 이벤트로 예를 듦)




html 항상 중첩이 되어있다. html -> body -> div


여기서 div에 click 이벤트가 있다고 가정하자. div를 클릭하면 어떻게 될까?


부모인 html, body 태그에 click 이벤트가 없다면 아무 상관이 없다.
하지만 html, body 태그에 click 이벤트가 있다면??
이 html, body 태그의 click 이벤트도 실행이 되어버림.. ㅠ



currentTarget은 자기 자신을 가르키는 것. (이미지 참고)
divtarget 이라 부름. 여기서 이벤트는 div 때문에 실행이 된 것이니까!



2. DOM의 event flow phase (실행순서)



  • html(document) 상위엔 window
  • 실행순서 (무조건 이 순서대로 흘러감!!)
  1. html -> body -> div 이것을 Capture phase라 부름
  2. 실행하려는 이벤트는 div 이것을 Target phase라 부름
  3. 마지막으로 다시 div -> body -> html로 돌아감 이것을 Bubble phase라 부름
  • 이미지 참고

  • propagate는 전파하다. 라는 뜻을 가지고 있음
  • 만약 div click 이벤트 실행하면..? 쓸데없이 body,html은 2번씩 실행되어버림..
    물론 body, html이 이벤트가 등록되어 있을 경우!
  • 브라우저의 event flow phase 중 실행 기본 값은 Bubble 설정되어 있음


3. DOM의 event flow phase (코드 예시)



<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        height: 100vh;
        background-color: cadetblue;
        width: 100%;
      }
      div {
        background-color: blueviolet;
        width: 100%;
      }
    </style>
  </head>
  <body>
    BODY
    <div>DIV</div>
    <script src="./script.js"></script>
  </body>
</html>
const html = document.documentElement;
const body = document.body;
const div = document.querySelector('div');

/* 
  * addEventListener의 3번째 매개변수
    - 안넣을 경우 기본값 false (bubble)
    - true로 넣어주면 capture
*/

// 여기서 div는 자식이 없음!! 굳이 캡쳐 or 버블을 선택하는 3번째 매개변수를 쓰지않아도 됨! 써봤자 소용없거든? 쓰지마!
div.addEventListener('click', () => {
  console.log('div 클릭');
});

body.addEventListener('click', () => {
  console.log('body 클릭');
});

html.addEventListener('click', () => {
  console.log('html 클릭');
});
  • 지금은 모두 기본값인 Bubble.
    div 클릭 시 결과는 div -> body -> html.

div.addEventListener('click', () => {
  console.log('div 클릭');
});

body.addEventListener(
  'click',
  () => {
    console.log('body 클릭');
  },
  true,
);

html.addEventListener(
  'click',
  () => {
    console.log('html 클릭');
  },
  true,
);
  • 이 코드처럼 3번째 매개변수에 bodyhtmltrue를 넣어주면?
    bodyhtmlCapture 상태가 됨.
    div 클릭 시 결과는 html -> body -> div.


+ 추가, 이벤트 버블링 & 캡쳐링 관련 함수



  • event.stopPropagation()
    이벤트 캡쳐링과 버블링에 있어 현재 이벤트 이후의 전파를 막음
  • mozilla : Event.stopPropagation()


참고 자료