Development Tip

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

yourdevel 2020. 9. 27. 14:12
반응형

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


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


이벤트 버블 링 및 캡처는 이벤트가 다른 요소 내부의 요소에서 발생하고 두 요소가 해당 이벤트에 대한 핸들을 등록한 경우 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첫 번째 (클릭 이벤트 핸들러가 div먼저 실행 됨), 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는 요소 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>

Please try with changing true and false.


I have found this tutorial at javascript.info to be very clear in explaining this topic. And its 3-points summary at the end is really talking to the crucial points. I quote it here:

  1. Events first are captured down to deepest target, then bubble up. In IE<9 they only bubble.
  2. All handlers work on bubbling stage excepts addEventListener with last argument true, which is the only way to catch the event on capturing stage.
  3. Bubbling/capturing can be stopped by event.cancelBubble=true (IE) or event.stopPropagation() for other browsers.

There's also the Event.eventPhase property which can tell you if the event is at target or comes from somewhere else.

Note that the browser compatibility is not determined yet. I tested it on Chrome (66.0.3359.181) and Firefox (59.0.3) and it is supported there.

Expanding on the already great snippet from the accepted answer, this is the output using the eventPhase property

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>


Bubbling

  Event propagate to the Upto root element is Bubbling.

Capturing

  Event propogate from body(root) element to eventTriggered Element is Capturing.

Extending others answer here

Event bubbling: Occuring events from innermost to outmost control.

Event captuing: Occuring events from outermost to innermost control.

addEventListener() method is used to enable/disable event bubbling and event capturing. This method has three parameters. If the third parameter (phase) is set to true event capturing is enabled and if it is set to false event bubbling is enabled (this is default behavior).

If you want both even bubbling and capturing to be enabled, then assign handlers 2 times, once with the phase parameter set to false and once with the phase parameter set to true as shown below.

<html>
<head>
    <style type="text/css">
        .divStyle
        {
            display: table-cell;
            border: 5px solid black;
            padding: 20px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="DIV1" class="divStyle">
        DIV 1
        <div id="DIV2" class="divStyle">
            DIV 2
            <div id="DIV3" class="divStyle">
                DIV 3
            </div>
        </div>
    </div>
    <script type="text/javascript">
        var divElements = document.getElementsByTagName('div');

        for (var i = 0; i < divElements.length; i++)
        {
            divElements[i].addEventListener("click", clickHandler, false);
            divElements[i].addEventListener("click", clickHandler, true);
        }

        function clickHandler()
        {
            alert(this.getAttribute("id") + " click event handled");
        }
    </script>
</body>
</html>

Please note : IE8 and earlier versions does not support addEventListener() method. This implies that event capturing is not supported in IE8 and earlier versions, and hence the above code will not work in IE 8 and earlier versions.

참고URL : https://stackoverflow.com/questions/4616694/what-is-event-bubbling-and-capturing

반응형