ReactJS SyntheticEvent stopPropagation() 仅适用于 React 事件?
我正在尝试在 ReactJS 组件中使用 event.stopPropagation() 来阻止单击事件冒泡并触发在遗留代码中附加到 JQuery 的单击事件,但似乎 React 的 stopPropagation() 仅停止传播到也附加在 React 中的事件,并且 JQuery 的 stopPropagation() 不会停止传播到 React 附加的事件.
有什么方法可以让 stopPropagation() 在这些事件中正常工作?我写了一个简单的 JSFiddle 来演示这些行为:
/** @jsx React.DOM */var 传播 = React.createClass({警报:函数(){alert('反应警报');},停止传播:函数(e){e.stopPropagation();},渲染:函数(){返回 (<div onClick={this.alert}><a href="#" onClick={this.stopPropagation}>React 事件停止传播</a></div><div className="alert"><a href="#" onClick={this.stopPropagation}>React 停止 JQuery 事件的传播</a></div><div onClick={this.alert}><a href="#" className="stop-propagation">JQuery 在 React 事件上停止传播</a></div><div className="alert"><a href="#" className="stop-propagation">JQuery 停止传播 JQuery 事件</a></div></div>);}});React.renderComponent(<传播/>, document.body);$(函数(){$(document).on('click', '.alert', function(e){alert('jQuery 警报');});$(document).on('click', '.stop-propagation', function(e){e.stopPropagation();});});
解决方案 React 使用事件委托和 document
上的单个事件侦听器来处理冒泡事件,例如本例中的点击",这意味着无法停止传播;当你在 React 中与它交互时,真实的事件已经传播了.stopPropagation
在 React 的合成事件上是可能的,因为 React 在内部处理合成事件的传播.
通过下面的修复工作JSFiddle.
在 jQuery 事件上反应停止传播
使用 Event.stopImmediatePropagation
以防止调用根上的其他(在本例中为 jQuery)侦听器.它在 IE9+ 和现代浏览器中受支持.
stopPropagation: function(e){e.stopPropagation();e.nativeEvent.stopImmediatePropagation();},
- 警告:监听器按绑定顺序调用.必须在其他代码(此处为 jQuery)之前初始化 React 才能使其正常工作.
jQuery 停止 React 事件的传播
您的 jQuery 代码也使用事件委托,这意味着在处理程序中调用 stopPropagation
不会停止任何事情;事件已经传播到 document
,React 的监听器会被触发.
//监听器绑定到`document`,事件委托$(document).on('click', '.stop-propagation', function(e){e.stopPropagation();});
为了防止传播到元素之外,监听器必须绑定到元素本身:
//监听器绑定到 `.stop-propagation`,没有委托$('.stop-propagation').on('click', function(e){e.stopPropagation();});
编辑(2016 年 1 月 14 日): 澄清委派必须仅用于冒泡事件.有关事件处理的更多详细信息,React 的源代码有描述性注释:ReactBrowserEventEmitter.js.
I'm trying to use event.stopPropagation() within a ReactJS component to stop a click event from bubbling up and triggering a click event that was attached with JQuery in legacy code, but it seems like React's stopPropagation() only stops propagation to events also attached in React, and JQuery's stopPropagation() doesn't stop propagation to events attached with React.
Is there any way to make stopPropagation() work across these events? I wrote a simple JSFiddle to demonstrate these behaviors:
/** @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 uses event delegation with a single event listener on document
for events that bubble, like 'click' in this example, which means stopping propagation is not possible; the real event has already propagated by the time you interact with it in React. stopPropagation
on React's synthetic event is possible because React handles propagation of synthetic events internally.
Working JSFiddle with the fixes from below.
React Stop Propagation on jQuery Event
Use Event.stopImmediatePropagation
to prevent your other (jQuery in this case) listeners on the root from being called. It is supported in IE9+ and modern browsers.
stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
},
- Caveat: Listeners are called in the order in which they are bound. React must be initialized before other code (jQuery here) for this to work.
jQuery Stop Propagation on React Event
Your jQuery code uses event delegation as well, which means calling stopPropagation
in the handler is not stopping anything; the event has already propagated to document
, and React's listener will be triggered.
// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
To prevent propagation beyond the element, the listener must be bound to the element itself:
// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
e.stopPropagation();
});
Edit (2016/01/14): Clarified that delegation is necessarily only used for events that bubble. For more details on event handling, React's source has descriptive comments: ReactBrowserEventEmitter.js.
相关文章