event.stopPropagation과 event.preventDefault의 차이점은 무엇입니까?


833

그들은 똑같은 일을하는 것 같습니다 ...
현대적이고 오래된 것입니까? 아니면 다른 브라우저에서 지원됩니까?

프레임 워크없이 이벤트를 직접 처리 할 때 항상 둘 다 확인하고 존재하는 경우 둘 다 실행합니다. (또한 return false이지만 첨부 된 이벤트에서는 작동하지 않는 느낌이 있습니다 node.addEventListener).

왜 둘 다? 둘 다 계속 확인해야합니까? 아니면 실제로 차이가 있습니까?

(나는 많은 질문을 알고 있지만 모두 같은 종류입니다 =)

답변:


1013

stopPropagation 이벤트가 이벤트 체인을 버블 링하지 못하게합니다.

preventDefault 브라우저가 해당 이벤트에 대해 수행하는 기본 동작을 방지합니다.

preventDefault

$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

전파 중지

$("#but").click(function (event) {
  event.stopPropagation()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

함께 stopPropagationbutton의 클릭 핸들러는 그동안라고 div의 클릭 핸들러는 ' 결코 발생합니다.

를 사용하는 것처럼 preventDefault브라우저의 기본 동작 만 중지되지만 div의 클릭 핸들러는 여전히 실행됩니다.

다음은 MDN의 DOM 이벤트 속성 및 메서드에 대한 문서입니다.

IE9 및 FF의 경우 preventDefault 및 stopPropagation을 사용할 수 있습니다.

IE8을 지원하고 대체 내리기 stopPropagationcancelBubble와 교체 preventDefaultreturnValue


그래서 그들은 매우 다르다? IE에는 두 가지 다른 이벤트 방법이 있습니까? 프레임 워크가 두 event.stop기능을 모두 수행하는 것이 이상합니다 . 또한 문제가 없었습니다. 나는 거품을 많이 사용합니다. 예를 주셔서 감사합니다!
Rudie

@Rudie는 브라우저 지원에 댓글을 달았습니다.
Raynos

7
그것의 가치 (경우에 당신은 MSDN의 문서에 보이지 않는) 지적이 cancelBubble하고 returnValue있는 두 속성 (그래서 설정해야합니다 cancelBubble = true;), 그 preventDefaultstopPropagation방법은 (소위해야하는 preventDefault();)
freefaller

1
@Raynos, 단 하나의 참고 사항 : event.stopPropagation ()은 이벤트 체인의 버블 링을 막을뿐만 아니라 캡처 단계에서 이벤트 전파를 중지합니다 ( developer.mozilla.org/en-US/docs/Web/ API / Event / stopPropagation )
Yuci

1
버튼 클릭에 대한 기본 동작이 무엇인지 아는 것이 도움이되므로 왜 stopDefault()같은 방식으로 작동하지 않는지 이해할 수 있습니다 stopPropagation(). 기본 액션이 onclick메소드를 호출하지 않으면 무엇입니까?
d512

249

술어

에서 quirksmode.org :

이벤트 캡처

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

               | |
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 \ / | |
| ------------------------- |
| 이벤트 캡쳐 |
-----------------------------------

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

이벤트 버블 링

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

               / \
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 | | | |
| ------------------------- |
| 이벤트 버블 링 |
-----------------------------------

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

W3C 이벤트 모델에서 발생하는 모든 이벤트는 대상 요소에 도달 할 때까지 캡처 된 후 다시 버블 링됩니다 .

                 | | / \
----------------- | |-| | -----------------
| element1 | | | | |
| ------------- | |-| | ----------- |
| | element2 \ / | | | |
| -------------------------------- |
| W3C 이벤트 모델 |
------------------------------------------

상호 작용

에서 w3.org 를 들어, 이벤트 캡처 :

캡처 EventListener가 이벤트의 추가 처리가 발생하지 않도록 stopPropagation하려면 Event인터페이스 의 메소드를 호출 할 수 있습니다. EventListeners동일한 계층 구조 레벨에 등록 된 추가 이벤트 가 계속 이벤트를 수신 하더라도 이벤트를 더 이상 디스패치하지 못하게 됩니다. 이벤트의 stopPropagation 메소드가 호출되면 해당 메소드에 대한 추가 호출은 추가 효과가 없습니다. 추가 캡처자가없고 stopPropagation호출되지 않은 경우, 이벤트 EventListeners는 대상 자체 에서 해당 트리거를 트리거합니다 .

대한 이벤트 버블 링 :

모든 이벤트 핸들러는 인터페이스 의 stopPropagation메소드를 호출하여 추가 이벤트 전파를 방지하도록 선택할 수 있습니다 Event. 어떤 경우 EventListener이 메소드를 호출, 모든 추가 EventListeners현재에는 EventTarget트리거하지만 그 수준에서 중단됩니다 버블 링됩니다. stopPropagation추가 버블 링을 방지하려면 한 번의 호출 만 필요합니다.

대한 이벤트 취소 :

취소는 EventpreventDefault 메소드 를 호출하여 수행됩니다 . 이벤트 플로우 단계 중 하나 이상의 EventListeners호출 preventDefault이 있으면 기본 조치가 취소됩니다.

다음 예에서 웹 브라우저에서 하이퍼 링크를 클릭하면 이벤트 흐름 (이벤트 리스너가 실행 됨) 및 이벤트 대상의 기본 동작 (새 탭이 열림)이 트리거됩니다.

HTML :

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>

자바 스크립트 :

var el = document.getElementById("c");

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
}

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
}

function bubblingOnClick1(ev) {
    el.innerHTML += "DIV event bubbling<br>";
}

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
}

// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);

예 1 : 출력 결과

DIV event capture
A event capture
A event bubbling
DIV event bubbling

예 2 : stopPropagation()함수에 추가

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.stopPropagation();
}

출력 결과

DIV event capture

이벤트 리스너는 이벤트의 하향 및 상향 전파를 방지했습니다. 그러나 기본 동작 (새 탭 열기)을 막지는 못했습니다.

예 3 : stopPropagation()함수에 추가

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
    ev.stopPropagation();
}

또는 기능

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
    ev.stopPropagation();
}

출력 결과

DIV event capture
A event capture
A event bubbling

두 이벤트 리스너가 동일한 이벤트 대상에 등록되어 있기 때문입니다. 이벤트 리스너는 이벤트가 더 이상 전파되는 것을 방지했습니다. 그러나 기본 조치 (새 탭 열기)를 방해하지 않았습니다.

예 4 : preventDefault() 를 들어 함수에 추가

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.preventDefault();
}

새 탭이 열리지 않도록합니다.


23
캡처와 버블 링의 더 깊은 구분에 감사 드리며 다른 답변은 jQuery 문제 만 해결합니다.
floribon

@floribon은 그의 대답에 대해 raynos를 화나게 할 의사가 없다고 말합니다.
Mahi

3
@ 마히 무엇? 나는 단지 사실을 말하고 있습니다. 허용 된 답변은 OP에서 가정하지 않은 jQuery를 사용하고 있기 때문에 실제 답변이 아닙니다. 그것은 단지 기술적 인 사실 일 뿐이며, 개인적이거나 불쾌한 사람은 없습니다.
floribon

2
귀하의 답변은 매우 체계적이고 진행 상황을 잘 보여줍니다. 처음에 나는 당신을 귀찮게하고 대답을 약간 변경하고 싶지 않았습니다. 왜냐하면 명확성을 위해 조금 개선 될 수 있다고 생각하기 때문입니다. 이 답변은 초보자에게 이벤트 모델을 설명하므로 초보자에게 줄 수있는 모든 원조가 먼 길을 가고 있다고 생각합니다. 내가 동의하지 않는 일반적인 주장 으로 내 편집 제안이 거부 되었습니다. @Ashkan에서 이러한 작은 변경 사항이 답변을 개선하는 데 도움이 될 수 있다고 생각되면이를 통합하십시오.
mucaho

68

거짓을 반환;


return false; 당신이 그것을 부를 때 3 개의 분리 된 일을합니다 :

  1. event.preventDefault() – 브라우저의 기본 동작을 중지합니다.
  2. event.stopPropagation() – 이벤트가 DOM을 전파 (또는 "버블 링")하지 못하게합니다.
  3. 콜백 실행을 중지하고 호출되면 즉시 반환합니다.

이 동작은 특히 return false이벤트가 버블 링되는 것을 막지 않는 일반적인 (jQuery가 아닌) 이벤트 핸들러와 다릅니다 .

preventDefault ();


preventDefault(); 한 가지 일을합니다 : 브라우저의 기본 동작을 중지합니다.

언제 사용합니까?


우리는 그들이 무엇을하지만 언제 사용해야하는지 알고 있습니까? 단순히 달성하려는 대상에 따라 다릅니다. preventDefault();기본 브라우저 동작을 "단지"방지 하려면 사용하십시오 . return false를 사용하십시오. 기본 브라우저 동작을 방지하고 이벤트가 DOM을 전파하지 못하게하려는 경우 대부분의 상황에서 false를 반환합니다. 당신이 정말로 원하는 것은 preventDefault()입니다.

예 :


예를 들어 이해하려고합시다.

순수한 JAVASCRIPT 예제를 볼 수 있습니다

예 1 :

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

위의 코드를 실행하면 하이퍼 링크 '여기를 클릭하십시오 stackoverflow.com' 을 클릭하십시오. 링크를 먼저 클릭하면 javascript 경고가 표시됩니다. Link Clicked Next를 클릭 하면 javascript 경고 div 가 표시됩니다. stackoverflow.com.

예 2 :

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

위의 코드를 실행하면 하이퍼 링크가 표시됩니다. '여기를 클릭하여 stackoverflow.com'을 클릭하십시오. 링크를 먼저 클릭하면 javascript 경고가 표시됩니다. Link Clicked Next를 클릭 하면 javascript 경고 div 가 표시됩니다. 'Click event prevented'텍스트로 대체 된 stackoverflow.com을 방문하려면 여기를 클릭하십시오. 그러면 stackoverflow.com으로 리디렉션 되지 않습니다 . 이는 기본 클릭 동작이 트리거되는 것을 방지하기 위해 사용한 event.preventDefault () 메소드 때문입니다.

예 3 :

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

이번에는 링크를 클릭하면 executeParent () 함수가 호출되지 않고 자바 스크립트 경고 div 가 표시되지 않습니다 . 이번에는 클릭 했습니다. 이는 event.stopPropagation () 메소드를 사용하여 상위 div로 전파되는 것을 방지했기 때문입니다. 다음으로 '클릭 이벤트가 실행될 예정입니다'라는 텍스트로 대체 된 '여기를 클릭하십시오 stackoverflow.com'하이퍼 링크가 표시되며 즉시 stackoverflow.com으로 리디렉션됩니다. event.preventDefault () 메소드를 사용하여 이번에는 기본 클릭 동작이 트리거되는 것을 막지 않았기 때문입니다.

예 4 :

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

링크를 클릭하면 executeParent () 함수가 호출되지 않고 자바 스크립트 경고가 표시되지 않습니다. 이는 event.stopPropagation () 메소드를 사용하여 상위 div로 전파되는 것을 방지했기 때문입니다. 다음으로 '클릭 이벤트 방지 됨'텍스트로 대체 된 '여기를 클릭하십시오 stackoverflow.com'하이퍼 링크가 표시되고 stackoverflow.com으로 리디렉션되지 않습니다. event.preventDefault () 메서드를 사용하여 이번에는 기본 클릭 동작이 트리거되지 않기 때문입니다.

예 5 :

거짓 반환의 경우 세 가지 예가 있으며 모두 똑같은 일을하는 것처럼 보입니다 (거짓을 반환하는 것). 실제로는 결과가 다릅니다. 위의 각 상황에서 실제로 발생하는 상황은 다음과 같습니다.

사례 :

  1. 인라인 이벤트 핸들러에서 false 를 반환 하면 브라우저가 링크 주소를 탐색하지 못하지만 이벤트가 DOM을 통해 전파되는 것을 막지는 않습니다.
  2. jQuery 이벤트 핸들러에서 false 를 반환 하면 브라우저가 링크 주소를 탐색하지 못하고 이벤트가 DOM을 통해 전파되지 않습니다.
  3. 일반 DOM 이벤트 핸들러에서 false 를 반환 하면 아무 것도 수행되지 않습니다.

세 가지 예를 모두 볼 수 있습니다.

  1. 인라인 반환 false.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
  var link = document.querySelector('a');

  link.addEventListener('click', function() {
    event.currentTarget.innerHTML = 'Click event prevented using inline html'
    alert('Link Clicked');
  });


  function executeParent() {
    alert('Div Clicked');
  }
</script>

  1. jQuery 이벤트 핸들러에서 false 를 반환 합니다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
  $('a').click(function(event) {
    alert('Link Clicked');
    $('a').text('Click event prevented using return FALSE');
    $('a').contents().unwrap();
    return false;
  });
  $('div').click(function(event) {
    alert('Div clicked');
  });
</script>

  1. 일반 DOM 이벤트 핸들러에서 false를 반환합니다.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
    return false
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

이 예들이 분명하기를 바랍니다. html 파일에서이 예제를 모두 실행하여 작동 방식을 확인하십시오.


1
jQuery가 이벤트 객체를 위조하기 때문에 기술적으로는 다르기 때문에 좋은 예제이지만 jQuery가 없으면 훨씬 더 좋을 것입니다.
Rudie

1
@ Rudie 내 대답을 업데이트하고 jquery를 제거하고 false 반환에 대한 예제를 추가했습니다.
Keval Bhatt

17

이것은 여기 에서 인용입니다

Event.preventDefault

preventDefault 메소드는 이벤트가 기본 기능을 수행하지 못하게합니다. 예를 들어, A 요소에서 preventDefault를 사용하여 해당 요소를 클릭하면 현재 페이지를 떠나지 않습니다.

//clicking the link will *not* allow the user to leave the page 
myChildElement.onclick = function(e) { 
    e.preventDefault(); 
    console.log('brick me!'); 
};

//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) { 
    console.log('you bricked my child!'); 
};

요소의 기본 기능은 제한적이지만 이벤트는 계속 DOM을 버블 링합니다.

Event.stopPropagation

두 번째 방법 인 stopPropagation은 이벤트의 기본 기능을 허용하지만 이벤트가 전파되지 않도록합니다.

//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) { 
    e.stopPropagation();
    console.log('prop stop! no bubbles!'); 
};

//since propagation was stopped by the child element's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};

stopPropagation은 부모 요소가 자식에 대해 주어진 이벤트를 알지 못하게 효과적으로 막습니다.

간단한 중지 방법을 사용하면 이벤트를 빠르게 처리 할 수 ​​있지만 버블 링으로 정확히 원하는 것을 생각하는 것이 중요합니다. 개발자가 정말로 원하는 것은 preventDefault 시간의 90 %입니다. 이벤트를 "정지"하면 잘못하여 수많은 문제가 발생할 수 있습니다. 플러그인이 작동하지 않고 타사 플러그인이 작동하지 않을 수 있습니다. 또는 더 나쁜 것은-코드가 사이트의 다른 기능을 손상시키는 것입니다.


2

Event.preventDefault- 브라우저 기본 동작을 중지합니다. 이제 브라우저 기본 동작이 무엇입니까. 앵커 태그가 있고 href 속성이 있고이 앵커 태그가 클릭 이벤트가있는 div 태그 안에 중첩되어 있다고 가정합니다. 앵커 태그의 기본 동작은 앵커 태그를 클릭하면 탐색해야하지만 event.preventDefault는이 경우 탐색을 중지합니다. 그러나 그것은 결코 사건의 버블 링 또는 사건의 확대를 멈추지 않습니다.

<div class="container">
 <a href="#" class="element">Click Me!</a>
</div>

$('.container').on('click', function(e) {
 console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  console.log('element was clicked');
});

결과는

"요소를 클릭했습니다"

"컨테이너를 클릭했습니다"

이제 event.StopPropation은 이벤트 버블 링 또는 이벤트 에스컬레이션을 중지합니다. 위의 예에서

$('.container').on('click', function(e) {
  console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  e.stopPropagation(); // Now the event won't bubble up
 console.log('element was clicked');
});

결과는

"요소를 클릭했습니다"

자세한 내용은이 링크를 참조하십시오 https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/


1

event.preventDefault(); 요소의 기본 동작이 발생하지 않도록합니다.

event.stopPropagation(); 이벤트가 DOM 트리를 버블 링하지 못하도록하여 상위 핸들러에게 이벤트를 알리지 못하게합니다.

예를 들어, 내부에 클릭 방법이 연결되어 DIV있거나 클릭 방법이 연결되어있는 링크가 있으면 또는 클릭 방법 FORM이 실행되지 않습니다.DIVFORM


-3

$("#but").click(function(event){
console.log("hello");
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.