이벤트 버블 링 및 캡처 란 무엇입니까?
이벤트 버블 링과 캡처의 차이점은 무엇입니까? 버블 링과 캡처는 언제 사용해야합니까?
이벤트 버블 링 및 캡처는 이벤트가 다른 요소 내부의 요소에서 발생하고 두 요소가 해당 이벤트에 대한 핸들을 등록한 경우 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
요소에 의해 처리됩니다 .
자세한 내용은
- QuirksMode의 이벤트 순서
- MDN의 addEventListener
- QuirksMode의 고급 이벤트
아래 예에서 강조 표시된 요소 중 하나를 클릭하면 이벤트 전파 흐름의 캡처 단계가 먼저 발생한 다음 버블 링 단계가 발생하는 것을 볼 수 있습니다.
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>
기술:
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:
- Events first are captured down to deepest target, then bubble up. In IE<9 they only bubble.
- All handlers work on bubbling stage excepts
addEventListener
with last argumenttrue
, which is the only way to catch the event on capturing stage.- Bubbling/capturing can be stopped by
event.cancelBubble=true
(IE) orevent.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
'Development Tip' 카테고리의 다른 글
sudo를 사용하여 쓰기 권한이없는 위치로 출력을 리디렉션하려면 어떻게해야합니까? (0) | 2020.09.28 |
---|---|
Java에서 2 * (i * i)가 2 * i * i보다 빠른 이유는 무엇입니까? (0) | 2020.09.28 |
virtualenv와 함께 다른 Python 버전 사용 (0) | 2020.09.27 |
C ++ 17의 새로운 기능은 무엇입니까? (0) | 2020.09.27 |
스크롤 막대를 숨기지 만 여전히 스크롤 할 수 있음 (0) | 2020.09.27 |