[javascript] 이벤트 버블 링 및 캡처 란 무엇입니까?

이벤트 버블 링과 캡처의 차이점은 무엇입니까? 버블 링 대 캡처는 언제 사용해야합니까?



답변

이벤트 버블 링 및 캡처는 다른 요소 내부의 요소에서 이벤트가 발생하고 두 요소가 해당 이벤트에 대한 핸들을 등록한 경우 HTML DOM API에서 이벤트 전파의 두 가지 방법입니다. 이벤트 전파 모드 는 요소가 이벤트를 수신하는 순서를 결정 합니다 .

버블 링을 통해 이벤트는 먼저 가장 안쪽 요소에 의해 캡처되고 처리 된 다음 외부 요소로 전파됩니다.

캡처하면 이벤트가 가장 바깥 쪽 요소에 의해 먼저 캡처되어 안쪽 요소로 전파됩니다.

캡처는 “트릭 링”이라고도하며 전파 순서를 기억하는 데 도움이됩니다.

물방울, 거품

예전에는 Netscape가 이벤트 캡처를 옹호했고 Microsoft는 이벤트 버블 링을 홍보했습니다. 둘 다 W3C Document Object Model Events 표준 (2000)의 일부입니다.

IE <9는 이벤트 버블 링 만 사용 하지만 IE9 + 및 모든 주요 브라우저는 둘 다를 지원합니다. 반면 에 복잡한 DOM 의 경우 이벤트 버블 링 성능이 약간 떨어질 수 있습니다 .

addEventListener(type, listener, useCapture)버블 링 (기본값) 또는 캡처 모드에서 이벤트 핸들러를 등록 하는 데 사용할 수 있습니다 . 캡처 모델을 사용하려면으로 세 번째 인수를 전달하십시오 true.

<div>
    <ul>
        <li></li>
    </ul>
</div>

위의 구조에서 li요소 에서 클릭 이벤트가 발생했다고 가정하십시오 .

캡처 모델에서 이벤트는 div첫 번째 ( divwill 에서 click 이벤트 핸들러가 먼저 실행 됨)에 의해 처리 된 다음 ul대상 요소에서 마지막으로 처리됩니다 li.

버블 링 모델에서는 반대 현상이 발생합니다. 이벤트는 먼저 li, 그 다음으로 ul, 마지막으로 div요소가 처리합니다.

자세한 내용은

아래 예에서 강조 표시된 요소를 클릭하면 이벤트 전파 흐름의 캡처 단계가 먼저 발생하고 버블 링 단계가 발생 함을 알 수 있습니다.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

function clearOutput() {
    logElement.innerHTML = "";
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>

JSFiddle의 또 다른 예 .


답변

기술:

quirksmode.org 에 이에 대한 멋진 설명이 있습니다. 간단히 말해서 (quirksmode에서 복사) :

이벤트 캡처

이벤트 캡처를 사용하는 경우

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

element1의 이벤트 핸들러가 먼저 실행되고 element2의 이벤트 핸들러가 마지막으로 실행됩니다.

이벤트 버블 링

이벤트 버블 링을 사용하는 경우

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

element2의 이벤트 핸들러가 먼저 실행되고 element1의 이벤트 핸들러가 마지막으로 실행됩니다.


무엇을 사용해야합니까?

그것은 당신이하고 싶은 것에 달려 있습니다. 더 나은 없습니다. 차이점은 이벤트 핸들러 실행 순서입니다. 대부분의 경우 버블 링 단계 에서 이벤트 핸들러를 시작하는 것이 좋지만 더 일찍 실행해야 할 수도 있습니다.


답변

요소 1과 요소 2가 2 개있는 경우 요소 2는 요소 1 안에 있고 두 요소가 모두 포함 된 이벤트 핸들러를 연결하면 onClick이라고 말할 수 있습니다. 이제 요소 2를 클릭하면 두 요소 모두에 대한 eventHandler가 실행됩니다. 이제 질문은 이벤트가 실행될 순서입니다. 요소 1에 첨부 된 이벤트가 먼저 실행되면 이벤트 캡처라고하고 요소 2에 첨부 된 이벤트가 먼저 실행되면이를 이벤트 버블 링이라고합니다. W3C에 따라 이벤트는 대상에 도달 할 때까지 캡처 단계에서 시작하여 요소로 돌아와 버블 링을 시작합니다.

캡처 및 버블 링 상태는 addEventListener 메소드의 useCapture 매개 변수로 알려져 있습니다.

eventTarget.addEventListener (type, listener, [, useCapture]);

기본적으로 useCapture는 false입니다. 그것은 버블 링 단계에 있다는 것을 의미합니다.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>

참과 거짓을 바꾸어보십시오.


답변

이 주제를 설명하는 데 javascript.info 에서이 학습서 가 매우 명확 하다는 것을 알았습니다 . 그리고 마지막 3 점 요약은 실제로 중요한 점에 대해 이야기하고 있습니다. 나는 여기에 인용한다.

  1. 이벤트는 먼저 가장 깊은 대상으로 캡처 된 다음 버블 업됩니다. IE <9에서는 거품 만 발생합니다.
  2. 모든 처리기 addEventListener는 마지막 인수를 제외 하고 버블 링 단계에서 작동하며
    true, 캡처 단계에서 이벤트를 포착하는 유일한 방법입니다.
  3. 버블 링 / 캡쳐는 event.cancelBubble=true(IE) 또는 event.stopPropagation()
    다른 브라우저에 의해 중지 될 수 있습니다 .

답변

Event.eventPhase이벤트가 대상에 있는지 또는 다른 곳에서 왔는지 알려줄 수 있는 속성 도 있습니다.

브라우저 호환성은 아직 결정되지 않았습니다. Chrome (66.0.3359.181) 및 Firefox (59.0.3)에서 테스트했으며 지원됩니다.

허용 된 답변에서 이미 훌륭한 스 니펫을 확장 하면 eventPhase속성을 사용하여 출력됩니다.

var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " +
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " +
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}
p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}
<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>


답변

버블 링

  Event propagate to the upto root element is **BUBBLING**.

캡처

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.


답변