web-dev-qa-db-ja.com

ReactJS SyntheticEvent stopPropagation()はReactイベントでのみ動作しますか?

ReactJSコンポーネント内でevent.stopPropagation()を使用して、クリックイベントがバブリングするのを停止し、レガシーコードのJQueryでアタッチされたクリックイベントをトリガーしようとしていますが、ReactのstopPropagation()はイベントへの伝播のみを停止するようですReactにも添付され、JQueryのstopPropagation()は、Reactに添付されたイベントへの伝播を停止しません。

これらのイベントでstopPropagation()を機能させる方法はありますか?これらの動作を示すために、簡単なJSFiddleを作成しました。

http://jsfiddle.net/7LEDT/3/

/** @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();
    });
});
101
lofiinterstate

Reactは、この例の「クリック」のようにバブルするイベントに対して、documentの単一のイベントリスナーでイベント委任を使用します。つまり、伝播を停止することはできません。実際のイベントは、Reactでイベントと対話するまでに既に伝播しています。 Reactは内部的に合成イベントの伝播を処理するため、Reactの合成イベントのstopPropagationは可能です。

以下からの修正でJSFiddleを動作させる: http://jsfiddle.net/7LEDT/6/

JQueryイベントでのReact Stopの伝播

ルート上の他の(この場合はjQuery)リスナーが呼び出されないようにするには、 Event.stopImmediatePropagation を使用します。 IE9 +および最新のブラウザーでサポートされています。

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
  • 警告:リスナーはバインドされた順に呼び出されます。 Reactは、これが機能するために他のコード(ここではjQuery)の前に初期化する必要があります。

ReactイベントでのjQuery Stop Propagation

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

編集(2016/01/14):委任は、必ずバブルするイベントにのみ使用されることを明確にしました。イベント処理の詳細については、Reactのソースに説明的なコメントがあります。 https://github.com/facebook/react/blob/b87aabd/packages/react-dom/src/events/ReactBrowserEventEmitter.js#L52-L85

139
Ross Allen

昨日この問題に遭遇したので、Reactに優しいソリューションを作成しました。

react-native-listener を確認してください。これまでのところ非常にうまく機能しています。フィードバックに感謝します。

7
Erik R.

コンポーネントに次を追加することでこれを解決できました。

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

まだ興味深い1つの瞬間です。

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

関数がタグでラップされている場合、この構造を使用します

この問題 から)documentにイベントをアタッチしている場合、e.stopPropagation()は役に立たないことに注意してください。回避策として、document.addEventListenerの代わりにwindow.addEventListener()を使用できます。その後、event.stopPropagation()は、イベントがウィンドウに伝播するのを停止します。

4
Jim Nielsen

更新:<Elem onClick={ proxy => proxy.stopPropagation() } />ができるようになりました

1
Eric Hodonsky