ReactJS SyntheticEvent stopPropagation()只适用于React事件

ReactJS SyntheticEvent stopPropagation() only works with React events?

本文关键字:适用于 React 事件 SyntheticEvent stopPropagation ReactJS      更新时间:2023-09-26

我试图在一个ReactJS组件中使用event.stopPropagation()来阻止点击事件冒气泡并触发在遗留代码中附加的JQuery的点击事件,但似乎React的stopPropagation()只会停止传播到也附加在React中的事件,而JQuery的stopPropagation()不会停止传播到附加在React中的事件。

是否有办法使stopPropagation()跨这些事件工作?我编写了一个简单的jsf来演示这些行为:

/** @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在document上使用带有单个事件侦听器的事件委托,例如本例中的'click',这意味着不可能停止传播;当你在React中与它交互时,真实的事件已经传播了。在React的合成事件上stopPropagation是可能的,因为React内部处理合成事件的传播。

正在工作的JSFiddle从下面修复

React停止jQuery事件传播

使用Event.stopImmediatePropagation来防止在根节点上的其他监听器(在本例中是jQuery)被调用。它支持IE9+和现代浏览器。

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
  • 警告:监听器是按照它们被绑定的顺序调用的。React必须在其他代码(这里是jQuery)之前初始化才能正常工作。

jQuery Stop Propagation on React Event

你的jQuery代码使用事件委托,以及,这意味着调用stopPropagation在处理程序是不停止任何东西;事件已经传播到document, React的监听器将被触发。

// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
    e.stopPropagation();
});

为了防止传播到元素之外,监听器必须绑定到元素本身:

// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
    e.stopPropagation();
});

Edit (2016/01/14):澄清委派必须仅用于冒泡的事件。有关事件处理的更多细节,React的源代码有描述性注释:ReactBrowserEventEmitter.js.

这仍然是一个有趣的时刻:

ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();

如果您的函数被标签

包装,请使用此结构

值得注意的是(从这个问题中),如果您将事件附加到document, e.stopPropagation()将不会有帮助。作为解决方法,您可以使用window.addEventListener()而不是document.addEventListener,然后event.stopPropagation()将阻止事件传播到窗口。

来自React文档:下面的事件处理程序是由冒泡阶段中的事件触发的。要为捕获阶段注册一个事件处理程序,附加capture 。(强调)

如果你有一个点击事件监听器在你的React代码,你不希望它冒泡,我认为你要做的是使用onClickCapture而不是onClick。然后将事件传递给处理程序,并执行event.nativeEvent.stopPropagation()以防止本机事件冒泡到普通JS事件侦听器(或任何未响应的事件)。

我可以通过向我的组件添加以下内容来解决这个问题:

componentDidMount() {
  ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
    event.stopPropagation();
  }, false);
}

React 17将事件委托给root而不是document,这可能会解决问题。更多细节请点击这里。你也可以参考我的博客

我昨天遇到了这个问题,所以我创建了一个对react友好的解决方案。

查看react-native-listener。到目前为止,它运行得很好。反馈感激。

一个快速的解决方法是使用window.addEventListener代替document.addEventListener

更新:<Elem onClick={ proxy => proxy.stopPropagation() } />

在我的情况下,e.stopPropagation()没有工作,因为孩子有onChange事件,父母onClick。从另一个StackOverflow答案中获得见解

更改事件和点击事件是不同的事件。

Meagning:在onChange内部调用e.stopPropagation()不会阻止onClick的触发。

解决方案有onChange或onClick。

我解决这个问题的方法是在回调时添加一个if语句,检查event.target,如果它与我期望的元素不同,然后从函数

返回

// Callback from my own app
function exitResultsScreen(event){
        // Check element by ID
        if (event.target.className !== sass.div__search_screen){return} 
        
       // Executed only when the right elements calls
        setShowResults(false)
}