event.stopPropagationとevent.preventDefaultの違いは何ですか?


834

彼らは同じことをしているようです...
1つはモダンで、もう1つは古いのですか?または、異なるブラウザでサポートされていますか?

(フレームワークなしで)自分でイベントを処理するときは、常に両方をチェックし、存在する場合は両方を実行します。(私もですがreturn false、が付いているイベントでは動作しないような気がしますnode.addEventListener)。

では、なぜ両方なのでしょうか。両方をチェックし続ける必要がありますか?それとも実際に違いがありますか?

(私は知っています、たくさんの質問ですが、それらはすべて同じです=))

回答:


1015

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>

stopPropagation

$("#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>

stopPropagation、唯一buttonのクリックハンドラは、一方で呼ばれているdivのクリックハンドラは、「決して火災。

を使用する場合と同様にpreventDefault、ブラウザのデフォルトアクションのみが停止しますが、divのクリックハンドラは引き続き発生します。

以下は、MDNのDOMイベントプロパティとメソッドに関するドキュメントです。

IE9とFFの場合は、preventDefaultとstopPropagationを使用できます。

IE8をサポートして置き換える下げることstopPropagationcancelBubbleして交換preventDefaultしてreturnValue


だから彼らはとても違うのですか?IEにも2つの異なるイベントメソッドがありますか?(それらは同じかもしれませんか??)フレームワークがそのevent.stop機能で両方を実行するのは奇妙です...また、奇妙なことに私はそれについて問題を経験したことがありません。バブリングをよく使います。例をありがとう!
ルディー

@Rudieがブラウザのサポートについてコメントしました。
Raynos、

7
これの注目に値する(場合には、あなたがMSDNのドキュメントを見ていない)ことcancelBubblereturnValueの両方の性質(そう設定する必要がありますcancelBubble = true;)、そしてそれpreventDefaultstopPropagationメソッド(そう呼ばれるべきですpreventDefault();
freefaller

1
@ Raynos、1つの注意:event.stopPropagation()は、イベントがイベントチェーンを泡立たせるのを停止するだけでなく、キャプチャ段階でのイベントの伝播も停止します(developer.mozilla.org/en-US/docs/Web/ API / Event / stopPropagation
Yuci

1
がとstopDefault()同じように機能しない理由を推測できるように、ボタンのクリックに対するデフォルトのアクションを知っておくと役立ちますstopPropagation()。デフォルトのアクションがonclickメソッドを呼び出さない場合、それは何ですか?
d512

249

用語

quirksmode.orgから:

イベントのキャプチャ

イベントキャプチャを使用する場合

               | |
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| |要素2 \ / | |
| ------------------------- |
| イベントのキャプチャ|
-----------------------------------

element1のイベントハンドラーが最初に起動し、element2のイベントハンドラーが最後に起動します。

イベントバブリング

イベントバブリングを使用する場合

               / \
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 | | | |
| ------------------------- |
| イベントバブリング|
-----------------------------------

element2のイベントハンドラーが最初に起動し、element1のイベントハンドラーが最後に起動します。

W3Cイベントモデルで発生するすべてのイベントは、ターゲット要素に到達するまで最初にキャプチャされ、その後再びふきだされます。

                 | | / \
----------------- | |-| | -----------------
| element1 | | | | |
| ------------- | |-| | ----------- |
| |要素2 \ / | | | |
| -------------------------------- |
| W3Cイベントモデル|
------------------------------------------

インターフェース

イベントキャプチャ用のw3.orgから:

キャプチャEventListenerがイベントのそれ以上の処理を発生させないようにしたい場合、インターフェースのstopPropagationメソッドを 呼び出すことができEventます。EventListeners同じ階層レベルで登録された追加のイベントは引き続き受信されますが、これによりイベントがそれ以上ディスパッチされなくなります。イベントのstopPropagation メソッドが呼び出されると、そのメソッドをさらに呼び出しても効果はありません。追加のキャプチャーが存在 stopPropagationせず、呼び出されていない場合、イベントEventListenersはターゲット自体で適切なトリガーをトリガーします。

以下のためのイベントバブリング

すべてのイベントハンドラーstopPropagationは、Eventインターフェイスのメソッドを呼び出すことにより、それ以上のイベントの伝播を防ぐことを選択できます。いずれか EventListenerがこのメソッドを呼び出すとEventListeners、現在のすべての追加EventTargetがトリガーされますが、そのレベルでバブリングは停止します。stopPropagationそれ以上のバブリングを防ぐために必要な呼び出しは1つだけです。

以下のためのイベントのキャンセル

キャンセルは、EventpreventDefault メソッドを呼び出すことによって行われます。イベントフローのいずれかのフェーズで1つ以上のEventListeners呼び出しpreventDefaultがあった場合、デフォルトのアクションはキャンセルされます。

次の例では、Webブラウザーのハイパーリンクをクリックすると、イベントのフロー(イベントリスナーが実行されます)とイベントターゲットのデフォルトアクション(新しいタブが開きます)がトリガーされます。

HTML:

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

JavaScript:

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

例2stopPropagation()関数に追加する

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

出力結果

DIV event capture

イベントリスナーは、イベントのそれ以上の下方および上方への伝播を防止しました。ただし、デフォルトのアクション(新しいタブが開く)は妨げられませんでした。

例3stopPropagation()関数に追加する

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

これは、両方のイベントリスナーが同じイベントターゲットに登録されているためです。イベントリスナーは、イベントのそれ以上の上方への伝播を防ぎました。ただし、デフォルトのアクション(新しいタブが開く)は妨げられませんでした。

例4preventDefault()たとえば、関数に追加する

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

新しいタブが開かないようにします。


23
キャプチャとバブリングのより深い区別に感謝しますが、他の回答はjQueryの懸念にのみ対処します。
floribon 2014年

@floribonは、あなたが彼の答えにレイノスを怒らせる意図はないと言っています。
Mahi 2016年

3
@まひ何?私は事実を言っているだけですが、受け入れられた答えはOPで想定されていないjQueryを使用しているため、私には実際の答えではありません。これは単なる技術的な事実であり、個人的なことや気分を害する人はいません。
floribon 2016年

2
あなたの答えは非常に体系的であり、何が起こっているかをうまく示しています。最初は私はあなたを煩わせたり、自分でいくつかの変更を加えたりしたくありませんでした。明確にするために少し改善できると思います。この回答は、初心者にイベントモデルを説明するものであるため、初心者に提供できるあらゆる支援は長い道のりを進んでいると思います。私の編集提案は、私が同意しない一般的な議論によって拒否されました。@Ashkanがあなたに、これらの小さな変更が回答の改善に役立つと感じた場合は、それらを組み込んでください。
mucaho

68

falseを返します。


return false; あなたがそれを呼び出すとき、3つの別々のことをします:

  1. event.preventDefault() –ブラウザのデフォルトの動作を停止します。
  2. event.stopPropagation() –イベントがDOMを伝播する(または「バブリングする」)のを防ぎます。
  3. コールバックの実行を停止し、呼び出されるとすぐに戻ります。

この動作は通常の(jQuery以外の)イベントハンドラーとは異なります。特に、return falseイベントが発生するのを防ぎません。

preventDefault();


preventDefault(); 1つのことを行います。これは、ブラウザーのデフォルトの動作を停止します。

いつ使うの?


私たちは彼らが何をするか知っていますが、いつ使うのですか?単にそれはあなたが達成したいことに依存します。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のアラートを取得します今すぐリンクのClickedあなたは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>

上記のコードハイパーリンクが表示されますを実行し、あなたがそのリンクをクリックした場合、最初のあなたはjavascriptのアラートを取得します今「stackoverflow.comここをクリックして」リンクのClickedあなたはjavascriptのアラートを取得します次のdivのClicked次のハイパーリンク」を参照されますがここをクリックして、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()は呼び出されず、JavaScriptアラートの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()は呼び出されず、JavaScriptアラートは表示されません。これは、event.stopPropagation()メソッドを使用して親divへの伝播を防止したためです。次に、ハイパーリンク「Click here to visit stackoverflow.com」がテキスト「Click event prevent」に置き換えられ、stackoverflow.comにリダイレクトされなくなります。これは、event.preventDefault()メソッドを使用して、今回はデフォルトのクリックアクションがトリガーされないようにしたためです。

例5:

falseを返す場合、3つの例があり、すべてまったく同じことをしているように見えます(ただfalseを返す)が、実際には結果はかなり異なります。上記のそれぞれで実際に起こることは次のとおりです。

ケース:

  1. インラインイベントハンドラーからfalseを返すと、ブラウザーはリンクアドレスに移動できなくなりますが、イベントがDOMを介して伝播することは停止しません。
  2. jQueryイベントハンドラーからfalseを返すと、ブラウザーがリンクアドレスに移動できなくなり、イベントがDOMを介して伝播するのを停止します。
  3. 戻る虚偽を通常のDOMイベントハンドラからは絶対に何もしません。

3つの例すべてが表示されます。

  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がなくてもさらに優れていたので、技術的には異なります。
ルディー

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

2番目のメソッド、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は、親要素が子の特定のイベントについて知るのを効果的に停止します。

単純な停止メソッドを使用すると、イベントをすばやく処理できますが、バブリングで何をしたいのかを正確に考えることが重要です。開発者が本当に望んでいるのは、90%の時間はpreventDefaultであることに間違いないと思います。イベントを誤って「停止」すると、将来、多くの問題が発生する可能性があります。プラグインが機能せず、サードパーティのプラグインがブリックされる可能性があります。さらに悪いことに、あなたのコードはサイトの他の機能を壊します。


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それはまた、添付のクリック方法があり、それは防ぐことができますDIVまたはFORM発射からメソッドをクリックします。


-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.