web-dev-qa-db-ja.com

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

彼らは同じことをしているようです...近代的なものと古いものはありますか?それとも別のブラウザでサポートされていますか?

私が自分自身でイベントを処理するとき(フレームワークなしで)、私はいつも両方をチェックし、もしあれば両方を実行します。 (私もreturn falseですが、node.addEventListenerが添付されたイベントではうまくいかないという気がします)。

それで、なぜ両方?両方をチェックし続けるべきですか?それとも実際に違いはありますか?

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

680
Rudie

stopPropagationは、イベントがイベントチェーンを膨らませるのを防ぎます。

preventDefaultは、ブラウザがそのイベントに対して行うデフォルトのアクションを防ぎます。

あなたがいるとしましょう

<div id="foo">
 <button id="but" />
</div>

$("#foo").click(function() {
   // mouse click on div
});

$("#but").click(function(ev) {
   // mouse click on button
   ev.stopPropagation();
});

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

stopPropagationでは、 ボタンクリックハンドラ のみが呼び出され、 divsクリックハンドラ は呼び出されません。

ちょうどpreventDefaultのようにブラウザのデフォルトアクションのみが停止されますが、divのクリックハンドラはまだ起動します。

以下はMDNMSDNからのDOMイベントオブジェクトに関するドキュメントです。

MDN:

IE9とFFでは、preventDefault&stopPropagationを使用できます。

IE8以下をサポートするには、stopPropagationcancelBubbleに置き換え、preventDefaultreturnValueに置き換えます。

870
Raynos

用語

からquirksmode.org

イベントキャプチャ

イベントキャプチャを使用するとき

 | | 
 --------------- | | ----------------- 
 | element1 | | | 
 | ----------- | | ----------- | 
 | | element2 \/| | 
 | ------------------------- | 
 |イベントのキャプチャ| 
 ----------------------------------- 

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

イベントバブリング

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

/\ 
 --------------- | | ----------------- 
 | element1 | | | 
 | ----------- | | ----------- | 
 | | element2 | | | | 
 | ------------------------- | 
 |イベントBUBBLING | 
 ----------------------------------- 

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

W3Cイベントモデルで発生したイベントは、ターゲット要素に到達するまで最初にキャプチャされ、その後再びバブルアップします

 | |/\ 
 ----------------- | |  -  | | ----------------- 
 | element1 | | | | | 
 | ------------- | |  -  | | ----------- | 
 | | element2 \/| | | | 
 | -------------------------------- | 
 | W3Cイベントモデル| 
 ----------------------------------------- -  

インタフェース

w3.org から、 イベントの取得

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

イベントバブリング の場合:

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

イベントキャンセル用

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

次の例では、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

例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();
}

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

204
Ashkan

return false;


return false;は、呼び出すときに3つの異なることを行います。

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

この動作は通常の(jQuery以外の)イベントハンドラとは異なることに注意してください。特に、return falseはイベントのバブリングを停止しません。

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

例5:

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

ケース:

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

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ファイルでこれらの例をすべて実行して、どのように機能するかを確認してください。

58
Keval Bhatt

これは からの引用です -

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は、親要素がその子の特定のイベントについて認識できないようにします。

単純なstopメソッドでイベントを素早く処理することができますが、バブリングで何が起きたいのかを考えることが重要です。私は、開発者が本当に望んでいるのはpreventDefault 90%の時間だけなのでしょう。イベントを誤って「停止」すると、さまざまなトラブルが発生する可能性があります。あなたのプラグインは動作しないかもしれず、あなたのサードパーティのプラグインはブリックされるかもしれません。あるいはさらに悪いことに、あなたのコードはサイト上の他の機能を壊します。

15
VladL

event.preventDefault();要素のデフォルトの動作を停止させます。

event.stopPropagation();イベントがDOMツリーを膨らませるのを防ぎ、親ハンドラにイベントが通知されるのを防ぎます。

たとえば、DIVまたはFORMの内側にクリックメソッドがアタッチされたリンクがある場合、それはDIVまたはFORM clickメソッドが起動するのを防ぎます。

1
Mike Clark

e.preventDefault()はデフォルトのイベントの発生を防ぎ、e.stopPropagation()はイベントの発生を防ぎ、falseを返すと両方を行います。

event.stopPropagation()を使用すると、同じ要素上の他のハンドラを実行できますが、event.stopImmediatePropagation()を使用すると、すべてのイベントが実行されなくなります。

1
Raghava

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

0