Qual è la differenza tra event.stopPropagation e event.preventDefault?


834

Sembrano fare la stessa cosa ...
Uno è moderno e uno vecchio? O sono supportati da diversi browser?

Quando gestisco gli eventi da solo (senza framework), controllo sempre entrambi ed eseguo entrambi, se presenti. (Anch'io return false, ma ho la sensazione che non funzioni con gli eventi collegati node.addEventListener).

Allora perché entrambi? Devo continuare a controllare per entrambi? O c'è davvero una differenza?

(Lo so, molte domande, ma sono tutte uguali =))

Risposte:


1015

stopPropagation impedisce all'evento di gorgogliare la catena di eventi.

preventDefault impedisce l'azione predefinita che il browser esegue su quell'evento.

Esempi

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>

Con stopPropagation, viene chiamato solo il buttongestore di clic del clic mentre il divgestore di clic del mouse non si attiva mai.

Dove se si utilizza preventDefault, viene interrotta solo l'azione predefinita del browser ma il gestore di clic del div viene comunque attivato.

Di seguito sono riportati alcuni documenti sulle proprietà e sui metodi dell'evento DOM di MDN:

Per IE9 e FF puoi semplicemente usare preventDefault e stopPropagation.

Per supportare IE8 e inferiori sostituire stopPropagationcon cancelBubblee sostituire preventDefaultconreturnValue


Quindi sono molto diversi? Anche per IE esistono due diversi metodi di eventi? (Potrebbero essere gli stessi ??) È strano che i framework facciano entrambi nella loro event.stopfunzione ... Strano anche che non ho mai avuto problemi con quello. Uso molto il gorgoglio. Grazie per l'esempio!
Rudie,

@Rudie ha commentato il supporto del browser.
Raynos,

7
Vale la pena notare (nel caso in cui non si guardino i documenti MSDN) che cancelBubblee returnValuesono entrambe proprietà (quindi dovrebbe essere impostato cancelBubble = true;), e che preventDefaulte stopPropagationsono metodi (quindi dovrebbe essere chiamato preventDefault();)
freefaller

1
@Raynos, solo una nota: event.stopPropagation () non solo impedisce all'evento di gorgogliare la catena di eventi, ma interrompe anche la propagazione degli eventi nella fase di acquisizione ( developer.mozilla.org/en-US/docs/Web/ API / Event / stopPropagation )
Yuci,

1
Sarebbe utile sapere quale sia l'azione predefinita per un clic sul pulsante, quindi posso ragionare sul perché stopDefault()non funziona allo stesso modo di stopPropagation(). Se l'azione predefinita non chiama il onclickmetodo, cos'è?
d512,

249

Terminologia

Da quirksmode.org :

Cattura di eventi

Quando si utilizza l'acquisizione di eventi

               | |
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 \ / | |
| ------------------------- |
| Evento CATTURAZIONE |
-----------------------------------

il gestore eventi di element1 viene attivato per primo, il gestore eventi di element2 viene attivato per ultimo.

Bolle di eventi

Quando si utilizza il gorgoglio degli eventi

               / \
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 | | | |
| ------------------------- |
| Evento BUBBLING |
-----------------------------------

il gestore di eventi di element2 viene attivato per primo, il gestore di eventi di element1 viene attivato per ultimo.

Qualsiasi evento che si svolge nel modello di eventi W3C viene prima catturato fino a quando non raggiunge l'elemento di destinazione e quindi bolle di nuovo .

                 | | / \
----------------- | | - | | -----------------
| element1 | | | | |
| ------------- | | - | | ----------- |
| | element2 \ / | | | |
| -------------------------------- |
| Modello di eventi W3C |
------------------------------------------

Interfaccia

Da w3.org , per l' acquisizione di eventi :

Se l'acquisizione EventListenerdesidera impedire l'ulteriore elaborazione dell'evento, può chiamare il stopPropagationmetodo Eventdell'interfaccia. Ciò impedirà un ulteriore invio dell'evento, anche se ulteriori EventListenersregistrazioni allo stesso livello gerarchico riceveranno comunque l'evento. Una volta stopPropagation chiamato il metodo di un evento , ulteriori chiamate a quel metodo non hanno alcun effetto aggiuntivo. Se non esistono altri catturatori e stopPropagationnon è stato chiamato, l'evento attiva l'appropriato EventListenerssul bersaglio stesso.

Per il gorgoglio degli eventi :

Qualsiasi gestore di eventi può scegliere di impedire un'ulteriore propagazione degli eventi chiamando il stopPropagationmetodo Eventdell'interfaccia. Se qualcuno EventListenerchiama questo metodo, verranno attivati tutti gli ulteriori EventListenerssulla corrente EventTargetma il gorgoglio cesserà a quel livello. È necessaria una sola chiamata stopPropagationper evitare ulteriori bolle.

Per la cancellazione di eventi :

Annullamento si ottiene chiamando il Event's preventDefault metodo. Se una o più EventListenerschiamate preventDefaultdurante qualsiasi fase del flusso di eventi, l'azione predefinita verrà annullata.

Esempi

Negli esempi seguenti, un clic sul collegamento ipertestuale nel browser Web attiva il flusso dell'evento (vengono eseguiti i listener di eventi) e l'azione predefinita della destinazione dell'evento (viene aperta una nuova scheda).

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);

Esempio 1 : risulta nell'output

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

Esempio 2 : aggiunta stopPropagation()alla funzione

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

risulta nell'output

DIV event capture

Il listener di eventi ha impedito un'ulteriore propagazione verso il basso e verso l'alto dell'evento. Tuttavia, non ha impedito l'azione predefinita (apertura di una nuova scheda).

Esempio 3 : aggiunta stopPropagation()alla funzione

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

o la funzione

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

risulta nell'output

DIV event capture
A event capture
A event bubbling

Questo perché entrambi i listener di eventi sono registrati sullo stesso target dell'evento. I listener di eventi hanno impedito un'ulteriore propagazione verso l'alto dell'evento. Tuttavia, non hanno impedito l'azione predefinita (apertura di una nuova scheda).

Esempio 4 : aggiunta preventDefault()a qualsiasi funzione, ad esempio

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

impedisce l'apertura di una nuova scheda.


23
Grazie per la più profonda distinzione tra cattura e gorgogliamento mentre l'altra risposta affronta solo le preoccupazioni di jQuery.
floribon,

@Floribon dice che non hai intenzione di offendere Raynos per la sua risposta.
Mahi,

3
@ Mahi cosa? Sto solo dicendo dei fatti, la risposta accettata sta usando jQuery che non è assunto dall'OP, quindi per me non è la risposta effettiva. Questo è solo un fatto tecnico, niente di personale e nessuno da offendere.
floribon,

2
La tua risposta è molto sistematica e dimostra bene cosa sta succedendo. Inizialmente non volevo disturbarti e apportare alcune modifiche alla tua risposta, perché penso che potrebbe essere migliorato un po 'per chiarezza. Questa risposta spiega il modello di evento per i principianti e, come tale, penso che ogni piccolo aiuto che possiamo dare ai principianti faccia molta strada. Il mio suggerimento di modifica è stato rifiutato da argomenti generici, con cui non sono d'accordo. Se tu, @Ashkan, ritieni che questi piccoli cambiamenti possano aiutare a migliorare la risposta, ti preghiamo di incorporarli.
mucaho,

68

restituire false;


return false; fa 3 cose separate quando lo chiami:

  1. event.preventDefault() - Arresta il comportamento predefinito del browser.
  2. event.stopPropagation() - Impedisce all'evento di propagare (o "gorgogliare") il DOM.
  3. Interrompe l'esecuzione della richiamata e ritorna immediatamente quando viene chiamato.

Si noti che questo comportamento differisce dai normali gestori di eventi (non jQuery), in cui, in particolare, return falsenon si impedisce all'evento di gorgogliare.

preventDefault ();


preventDefault(); fa una cosa: interrompe il comportamento predefinito del browser.

Quando usarli?


Sappiamo cosa fanno ma quando usarli? Semplicemente dipende da cosa vuoi realizzare. Utilizzare preventDefault();se si desidera "solo" impedire il comportamento predefinito del browser. Usa return false; quando si desidera impedire il comportamento predefinito del browser e impedire all'evento di propagare il DOM. Nella maggior parte delle situazioni in cui potresti usare return false; quello che vuoi davvero è preventDefault().

Esempi:


Proviamo a capire con esempi:

Vedremo puro esempio JAVASCRIPT

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

Esegui il codice sopra vedrai il collegamento ipertestuale 'Fai clic qui per visitare stackoverflow.com' ora se fai clic prima su quel link riceverai l'avviso javascript Collegamento Fare clic su Avanti Verrà visualizzato l'avviso javascript div Fare clic e immediatamente verrai reindirizzato a stackoverflow.com.

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

Esegui il codice sopra vedrai il collegamento ipertestuale 'Fai clic qui per visitare stackoverflow.com' ora se fai clic su quel collegamento prima otterrai l'avviso javascript Collegamento Fai clic su Avanti otterrai l'avviso javascript div Fare clic su Avanti vedrai il collegamento ipertestuale ' Clicca qui per visitare stackoverflow.com' sostituito dal testo 'Clicca evento prevenuto' e sarà non essere reindirizzato a stackoverflow.com. Ciò è dovuto al metodo event.preventDefault () che abbiamo usato per impedire l'attivazione dell'azione di clic predefinita.

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

Questa volta, se si fa clic su Collegamento, la funzione executeParent () non verrà chiamata e non verrà visualizzato il div avviso javascript. Fare clic questa volta. Ciò è dovuto al fatto che abbiamo impedito la propagazione al div padre utilizzando il metodo event.stopPropagation (). Successivamente vedrai il collegamento ipertestuale "Fai clic qui per visitare stackoverflow.com" sostituito dal testo "L'evento clic verrà eseguito" e immediatamente verrai reindirizzato a stackoverflow.com. Questo perché non abbiamo impedito che l'azione di clic predefinita venga attivata questa volta utilizzando il metodo event.preventDefault ().

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

Se si fa clic sul collegamento, la funzione executeParent () non verrà chiamata e non verrà visualizzato l'avviso javascript. Ciò è dovuto al fatto che abbiamo impedito la propagazione al div padre utilizzando il metodo event.stopPropagation (). Successivamente vedrai il collegamento ipertestuale 'Fai clic qui per visitare stackoverflow.com' sostituito dal testo 'Evento clic impedito' e non verrai reindirizzato a stackoverflow.com. Questo perché abbiamo impedito che l'azione di clic predefinita venga attivata questa volta utilizzando il metodo event.preventDefault ().

Esempio 5:

Per return false ho tre esempi e tutti sembrano fare esattamente la stessa cosa (solo restituendo false), ma in realtà i risultati sono abbastanza diversi. Ecco cosa succede effettivamente in ciascuno dei precedenti.

casi:

  1. La restituzione di false da un gestore eventi inline impedisce al browser di navigare verso l'indirizzo del collegamento, ma non impedisce la propagazione dell'evento attraverso il DOM.
  2. La restituzione di false da un gestore eventi jQuery impedisce al browser di navigare verso l'indirizzo del collegamento e impedisce la propagazione dell'evento attraverso il DOM.
  3. Restituire false da un normale gestore di eventi DOM non fa assolutamente nulla.

Vedremo tutti e tre gli esempi.

  1. Inline return 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. Restituzione di false da un gestore eventi jQuery.

<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. Restituzione di false da un normale gestore di eventi DOM.

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

Spero che questi esempi siano chiari. Prova a eseguire tutti questi esempi in un file html per vedere come funzionano.


1
Buoni esempi, ma sarebbe stato ancora meglio senza jQuery, perché jQuery falsifica l'oggetto evento, quindi tecnicamente diverso.
Rudie,

1
@Rudie Ho aggiornato la mia risposta e rimosso jquery da essa, e ho anche aggiunto un esempio per return false.
Keval Bhatt,

17

Questa è la citazione da qui

Event.preventDefault

Il metodo preventDefault impedisce a un evento di eseguire la sua funzionalità predefinita. Ad esempio, dovresti usare preventDefault su un elemento A per interrompere il clic su quell'elemento in modo da uscire dalla pagina corrente:

//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!'); 
};

Mentre la funzionalità predefinita dell'elemento è in muratura, l'evento continua a creare bolle nel DOM.

Event.stopPropagation

Il secondo metodo, stopPropagation, consente la funzionalità predefinita dell'evento ma impedisce la propagazione dell'evento:

//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 impedisce efficacemente agli elementi principali di conoscere un determinato evento sul proprio figlio.

Mentre un semplice metodo di arresto ci consente di gestire rapidamente gli eventi, è importante pensare a cosa esattamente vuoi che accada con il gorgoglio. Scommetto che tutto ciò che uno sviluppatore vuole davvero è prevenire Default 90% del tempo! "Interrompere" erroneamente un evento potrebbe causare numerosi problemi lungo la linea; i plug-in potrebbero non funzionare e i plug-in di terze parti potrebbero essere bloccati. O peggio ancora: il tuo codice rompe altre funzionalità su un sito.


2

Event.preventDefault: arresta il comportamento predefinito del browser. Ora arriva qual è il comportamento predefinito del browser. Supponiamo che tu abbia un tag anchor e che abbia un attributo href e che questo tag anchor sia nidificato all'interno di un tag div con un evento click. Il comportamento predefinito del tag anchor è quando si fa clic sul tag anchor che dovrebbe navigare, ma ciò che fa event.preventDefault è che interrompe la navigazione in questo caso. Ma non ferma mai il gorgoglio degli eventi o l'escalation degli eventi, ad es

<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');
});

Il risultato sarà

"elemento è stato cliccato"

"contenitore selezionato"

Ora event.StopPropation interrompe il gorgoglio dell'evento o l'escalation dell'evento. Ora con l'esempio sopra

$('.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');
});

Il risultato sarà

"elemento è stato cliccato"

Per maggiori informazioni consultare questo link https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/


1

event.preventDefault(); Impedisce che si verifichi l'azione predefinita di un elemento.

event.stopPropagation(); Impedisce all'evento di gorgogliare l'albero del DOM, impedendo a qualsiasi gestore padre di essere informato dell'evento.

Ad esempio, se è presente un collegamento con un metodo clic collegato all'interno di DIVo FORMcon un metodo clic collegato, verrà impedito l' attivazione del metodo DIVo FORMclic.


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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.