본문 바로가기
CS/javascript

[javascript] 이벤트 버블링, 캡처링

by kyj0032 2024. 4. 19.
<div onclick="alert('div에 할당한 핸들러!')">
  <em><code>EM</code>을 클릭했는데도 <code>DIV</code>에 할당한 핸들러가 동작합니다.</em>
</div>
EM을 클릭했는데도 DIV에 할당한 핸들러가 동작합니다.

<div> 안에 있는 <em>, <code>를 눌러도 div에 할당된 onclick 이벤트 핸들러가 작동한다.

처음엔 그냥 div가 div 안 전체 영역을 포함하는 것(트리구조)이라 그런 게 아닐까?라고 생각했지만.. 그거랑 별개로 이벤트 버블링이 동작하는 거라 그런 거였다. 이벤트 버블링으로 내가 생각한 "포함하는 구조"라는 직관적 개념이 구현되는 듯

 

1. 이벤트 버블링

한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고 부모 요소의 핸들러가 동작한다. 부모의 부모를 거슬러 가면서 최상단의 요소까지 모든 할당된 이벤트 핸들러를 실행한다.'

<form onclick="alert('form')">FORM
	<div onclick="alert('div')">DIV
    	<p onclick="alert('p'")>P </p>
    </div>
</form>

 

FORM
DIV

P

 

가장 안 쪽의 <p>를 클릭하면 p -> div -> form 순서대로 부모를 거슬러 올라가며 이벤트 핸들러가 동작하는 것을 볼 수 있다.

 

https://ko.javascript.info/bubbling-and-capturing

 

버블링은 거의 모든 이벤트에서 실행된다.

* focus(입력창에 focus 된 상태, <-> blur)는 버블링이 발생하지 않는다

 

2. event.target, this, event.currentTarget

  • event.target: 실제 이벤트가 일어난 element
  • this(= event.currentTarget): 현재 실행 중인 핸들러가 할당된 element, 요소
form.onclick = function(event) {
  event.target.style.backgroundColor = 'yellow';

  // chrome needs some time to paint yellow
  setTimeout(() => {
    alert("target = " + event.target.tagName + ", this=" + this.tagName);
    event.target.style.backgroundColor = ''
  }, 0);
};

3. 버블링 중단하기

  • event.stopPropagation()
    • 해당 이벤트 핸들러 요소 위로는 버블링이 전달되지 않는다
  • event.stopImmediatePropagation()
    • 버블링을 멈추고, 할당된 다른 이벤트 핸들러들도 모두 멈춘다

4. 캡처링, 타겟, 버블링

 

*DOM 이벤트에서 정의한 이벤트 흐름

  1. 캡처링: 최상위 조상 ~~> 타겟까지 이벤트가 하위 요소로 전파되는 단계
  2. 타겟: 이벤트가 실제 타겟 요소에 전달되는 단계
  3. 버블링: 타겟 ~~> 최상위 조상까지 이벤트가 상위 요소로 전파되는 단계
elem.addEventListener(..., {capture: true})
elem.addEventListener(..., true)

캡처링은 addEventListener의 세번째 인자에 boolean값을 넘겨주는 것으로 캐치할 수 있다

 

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form>FORM
  <div>DIV
    <p>P</p>
  </div>
</form>

<script>
  for(let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alert(`캡쳐링: ${elem.tagName}`), true);
    elem.addEventListener("click", e => alert(`버블링: ${elem.tagName}`));
  }
</script>

 

 

 

여기서 Window와 Document란 무엇일까?

여기저기 찾아보다가 공식문서에도 설명이 친절하게 되어있는 것을 발견했다 공식문서부터 찾아보는 걸 습관화하자

https://developer.mozilla.org/ko/docs/Web/API/Window
https://developer.mozilla.org/ko/docs/Web/API/Document

 

Window 인터페이스는 DOM 문서를 담은 창을 나타냅니다. document 속성이 창에 불러온 DOM 문서를 가리킵니다.

Document 인터페이스는 브라우저가 불러온 웹 페이지를 나타내며, 페이지 콘텐츠(DOM 트리)의 진입점 역할을 수행합니다. DOM 트리는 <body> <table> (en-US)  여러 다른 요소를 포함합니다. Document는 페이지의 URL을 얻거나 문서에 새로운 요소를 생성하는 등의 기능을 전역적으로 제공합니다.