J'essaie d'utiliser event.stopPropagation () dans un composant ReactJS pour empêcher un événement click de se propager et de déclencher un événement click associé à JQuery dans du code hérité, mais il semble que stopPropagation () de React arrête uniquement la propagation aux événements également attaché dans React, et stopPropagation () de JQuery n'arrête pas la propagation aux événements attachés avec React.
Est-il possible de faire en sorte que stopPropagation () agisse sur tous ces événements? J'ai écrit un simple JSFiddle pour démontrer ces comportements:
/** @jsx React.DOM */
var Propagation = React.createClass({
alert: function(){
alert('React Alert');
},
stopPropagation: function(e){
e.stopPropagation();
},
render: function(){
return (
<div>
<div onClick={this.alert}>
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on React Event</a>
</div>
<div className="alert">
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on JQuery Event</a>
</div>
<div onClick={this.alert}>
<a href="#" className="stop-propagation">JQuery Stop Propagation on React Event</a>
</div>
<div className="alert">
<a href="#" className="stop-propagation">JQuery Stop Propagation on JQuery Event</a>
</div>
</div>
);
}
});
React.renderComponent(<Propagation />, document.body);
$(function(){
$(document).on('click', '.alert', function(e){
alert('Jquery Alert');
});
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
});
React utilise la délégation d'événements avec un écouteur d'événement unique sur document
pour les événements qui apparaissent comme "clic" dans cet exemple, ce qui signifie que l'arrêt de la propagation n'est pas possible. l'événement réel s'est déjà propagé au moment où vous interagissez avec lui dans React. stopPropagation
sur l'événement synthétique de React est possible car React gère la propagation des événements synthétiques en interne.
Utilisez Event.stopImmediatePropagation
pour éviter que vos autres écouteurs (jQuery dans ce cas) de la racine soient appelés. Il est pris en charge dans les navigateurs IE9 + et modernes.
_stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
},
_
Votre code jQuery utilise également la délégation d'événements, ce qui signifie que l'appel de stopPropagation
dans le gestionnaire n'arrête rien; l'événement a déjà été propagé à document
et l'auditeur de React sera déclenché.
_// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
_
Pour empêcher la propagation au-delà de l'élément, l'auditeur doit être lié à l'élément lui-même:
_// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
e.stopPropagation();
});
_
Edit (2016/01/14): Clarifié que la délégation n'est nécessairement utilisée que pour les événements en bulle. Pour plus de détails sur la gestion des événements, les sources de React ont des commentaires descriptifs: ReactBrowserEventEmitter.js .
C'est encore un moment intéressant:
ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();
Utilisez cette construction, si votre fonction est encapsulée par tag
J'ai pu résoudre ce problème en ajoutant les éléments suivants à mon composant:
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
event.stopPropagation();
}, false);
}
J'ai rencontré ce problème hier et j'ai donc créé une solution conviviale pour React.
Découvrez react-native-listener . Cela fonctionne très bien jusqu'à présent. Commentaires appréciés.
Il est à noter (de this issue ) que si vous attachez des événements à document
, e.stopPropagation()
ne vous aidera pas. Pour contourner le problème, vous pouvez utiliser window.addEventListener()
au lieu de document.addEventListener
, puis event.stopPropagation()
empêchera l’événement de se propager à la fenêtre.
Mise à jour: vous pouvez maintenant <Elem onClick={ proxy => proxy.stopPropagation() } />