ReactJS SyntheticEvent stopPropagation () केवल रिएक्ट घटनाओं के साथ काम करता है?


126

मैं ReactJS घटक के भीतर event.stopPropagation () का उपयोग करने की कोशिश कर रहा हूं, एक क्लिक ईवेंट को बुदबुदाने से रोकने के लिए और एक क्लिक ईवेंट को ट्रिगर करने के लिए जो लीगेसी कोड में JQuery के साथ जुड़ा हुआ था, लेकिन ऐसा लगता है कि रिएक्ट के स्टॉपप्रॉपैगनेशन () केवल घटनाओं के प्रसार को रोकता है React में भी संलग्न है, और JQuery के stopPropagation () React से जुड़ी घटनाओं के प्रसार को नहीं रोकता है।

क्या इन घटनाओं में स्टॉपप्रॉपैगैशन () काम करने का कोई तरीका है? मैंने इन व्यवहारों को प्रदर्शित करने के लिए एक साधारण JSFiddle लिखा है :

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

9
रिएक्ट का वास्तविक ईवेंट श्रोता भी दस्तावेज़ के मूल में है, जिसका अर्थ है कि क्लिक इवेंट पहले ही रूट पर bubbled है। आप event.nativeEvent.stopImmediatePropagationअन्य ईवेंट श्रोताओं को गोलीबारी से रोकने के लिए उपयोग कर सकते हैं , लेकिन निष्पादन के आदेश की गारंटी नहीं है।
रॉस एलन

3
दरअसल, stopImmediatePropagationदावा घटना श्रोताओं को उस क्रम में बुलाया जाएगा जिसमें वे बाध्य थे। यदि आपका रिएक्ट जेएस आपके jQuery (जैसा कि आपके फिडेल में है) से पहले आरंभीकृत किया जाता है, तो तत्काल प्रसार को रोकना काम करेगा।
रॉस एलन

JQuery के श्रोताओं को बुलाया जाने से रोकने के लिए प्रतिक्रिया दें: jsfiddle.net/7LEDT/5 प्रतिक्रिया को रोकने के लिए jQuery के लिए संभव नहीं है क्योंकि jQuery के श्रोताओं को बाद में आपकी पहेली में बाध्य किया जाता है।
रॉस एलन

एक विकल्प यह होगा कि आप अपना स्वयं का jQuery इवेंट हैंडलर सेट करें componentDidMount, लेकिन यह अनपेक्षित तरीके से अन्य रिएक्ट इवेंट हैंडलर के साथ हस्तक्षेप कर सकता है।
डगलस

मुझे एहसास हुआ कि दूसरा उदाहरण .stop-propagationजरूरी काम नहीं करेगा। आपका उदाहरण ईवेंट प्रतिनिधिमंडल का उपयोग करता है, लेकिन तत्व पर प्रसार को रोकने की कोशिश कर रहा है। श्रोता को स्वयं तत्व से बंधे रहने की आवश्यकता है $('.stop-propagation').on('click', function(e) { e.stopPropagation(); });:। यह फ़ेल्ड आपके द्वारा किए जा रहे सभी प्रचार को रोकता है: jsfiddle.net/7LEDT/6
रॉस एलन

जवाबों:


165

प्रतिक्रिया उस घटना के लिए एक एकल घटना श्रोता के साथ इवेंट डेलिगेशन का उपयोग documentकरती है, जैसे कि इस उदाहरण में 'क्लिक', जिसका अर्थ है कि प्रचार को रोकना संभव नहीं है; वास्तविक घटना पहले ही उस समय तक प्रचारित हो जाती है जब आप इसके साथ प्रतिक्रिया करते हैं। stopPropagationरिएक्ट की सिंथेटिक घटना पर संभव है क्योंकि रिएक्ट आंतरिक रूप से सिंथेटिक घटनाओं के प्रसार को संभालता है।

काम JSFiddle नीचे से सुधार के साथ।

प्रतिक्रिया रोकें jQuery इवेंट पर प्रचार

Event.stopImmediatePropagationअपने अन्य (इस मामले में jQuery) को रोकने के लिए उपयोग किया जा रहा है पर श्रोताओं को बुलाया जा रहा है। यह IE9 + और आधुनिक ब्राउज़रों में समर्थित है।

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
  • कैविएट: श्रोताओं को उस क्रम में बुलाया जाता है जिसमें वे बाध्य होते हैं। इस कार्य के लिए अन्य कोड (jQuery यहां) से पहले प्रतिक्रिया शुरू की जानी चाहिए।

jQuery रिएक्ट इवेंट पर प्रचार बंद करो

आपका jQuery कोड ईवेंट प्रतिनिधिमंडल का उपयोग करता है, जिसका अर्थ stopPropagationहै कि हैंडलर में कॉल करना कुछ भी नहीं रोक रहा है; घटना पहले से ही प्रचारित है document, और रिएक्ट के श्रोता को ट्रिगर किया जाएगा।

// 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): स्पष्ट है कि प्रतिनिधिमंडल केवल उन घटनाओं के लिए उपयोग किया जाता है जो बुलबुला है। इवेंट हैंडलिंग पर अधिक जानकारी के लिए, रिएक्ट के स्रोत में वर्णनात्मक टिप्पणियां हैं: ReactBrowserEventEmitter.js


@ लॉरेलन: क्लेरीफिकेशन: रिएक्ट इसकी घटना श्रोता को documentया रूट रिएक्ट घटक पर बांधता है ? लिंक किए गए पृष्ठ सिर्फ कहते हैं, जो मेरा मतलब है कि यह ले "शीर्ष स्तर पर" नहींdocument (लेकिन मैं समझ नहीं करता है, तो यह भी प्रासंगिक है)।
user128216

2
@ फाइटरजेट जो ईवेंट प्रकार पर निर्भर करता है। बुलबुले कि घटनाओं के लिए, शीर्ष-स्तरीय प्रतिनिधिमंडल का उपयोग किया जाता है। बुलबुला नहीं है कि घटनाओं के लिए, प्रतिक्रिया आवश्यक रूप से विभिन्न डोम नोड पर सुनता है। एक अधिक गहन वर्णन ReactBrowserEventEmitter.js में शामिल है: github.com/facebook/react/blob/…
रॉस एलन

अस्थायी पतन के लिए मेरी माफी। मुझे बग रिपोर्ट के लिए इसकी आवश्यकता थी और मैंने इसे
अपवोट के

जिम के जवाब को भी देखें, जो windowइसके बजाय ग्लोबल क्लिक श्रोता को जोड़ने का सुझाव देता है document: stackoverflow.com/a/52879137/438273
jsejcksn

13

वर्थ नोटिंग ( इस मुद्दे से ) कि अगर आप घटनाओं को संलग्न कर रहे हैं document, e.stopPropagation()तो मदद करने वाला नहीं है। वर्कअराउंड के रूप में, आप window.addEventListener()इसके बजाय का उपयोग कर सकते हैं document.addEventListener, फिर event.stopPropagation()विंडो को प्रचारित करने से घटना को रोक देगा।


आपका बहुत बहुत धन्यवाद! यह वास्तव में मेरे पास है और यह समाधान काम करता है।
एह त्रान

10

यह अभी भी एक अंतरंग क्षण है:

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

यदि आपका फ़ंक्शन टैग द्वारा लिपटा हुआ है, तो इस निर्माण का उपयोग करें


1
event.nativeEventसही उत्तर है; मैं इसके माध्यम से उपयोग करने में सक्षम था composedPath():event.nativeEvent.composedPath()
jimmont

क्या मतलब wrapped by tag? क्या आप pls एक उदाहरण प्रदान कर सकते हैं?
जिमीएलवी

@ जिमीएलवी मेरा मतलब है <div onClick=(firstHandler)> <div onClick=(secHandler)>active text</div> </div>
रोमन

7

मैं निम्नलिखित को अपने घटक में जोड़कर इसे हल करने में सक्षम था:

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

2
यह SynteticEvents को पूरी तरह से रोक देगा, क्योंकि React उस घटना के लिए दस्तावेज़ पर एकल ईवेंट श्रोता के साथ ईवेंट प्रतिनिधिमंडल का उपयोग करता है।
वख्तंग

5

मैं कल इस समस्या में भाग गया, इसलिए मैंने एक प्रतिक्रिया-अनुकूल समाधान बनाया।

प्रतिक्रिया-मूल-श्रोता की जाँच करें । यह अब तक बहुत अच्छा काम कर रहा है। प्रतिक्रिया की सराहना की।


5
react-native-listenerउपयोगों findDomNodeको
घटाया

नीचा दिखाया गया है क्योंकि उत्तर बाजार के लिए एक उपयुक्त जगह नहीं है या बाहरी समाधान नहीं हैं जो एक पूर्ण उत्तर के पूरक नहीं हैं।
जिंमोंट

2

से प्रतिक्रिया प्रलेखन : नीचे ईवेंट हैंडलर्स कर रहे हैं शुरू हो रहा एक घटना से उत्साह से भरा हुआ चरण में । कैप्चर चरण के लिए ईवेंट हैंडलर रजिस्टर करने के लिए, कैप्चर को जोड़ें । (महत्व दिया)

यदि आपके पास अपने रिएक्ट कोड में एक क्लिक ईवेंट श्रोता है और आप इसे बबल नहीं करना चाहते हैं, तो मुझे लगता है कि आप onClickCaptureइसके बजाय क्या करना चाहते हैं onClick। तब आप ईवेंट को हैंडलर को दे देंगे और event.nativeEvent.stopPropagation()नेटिव इवेंट को बुबिला से लेकर वेनिला जेएस ईवेंट श्रोता (या ऐसी कोई भी चीज़ जो प्रतिक्रिया नहीं दे) तक रखने के लिए करेंगे।


0

अद्यतन: अब आप कर सकते हैं <Elem onClick={ proxy => proxy.stopPropagation() } />


1
@ RossAllen का उत्तर देखें। यह पूर्वज के मूल डोम श्रोताओं (जो jQuery का उपयोग करता है) के प्रसार को नहीं रोकेगा।
बेन मोजर 21

यदि आप एक प्रतिक्रिया घटक का उपयोग कर रहे हैं तो यह सही तरीका है। घटना को हाईजैक करना एक अच्छा विचार नहीं है।
एरिक होडोंस्की

अगर कुछ और विफल हो रहा है, तो ऐसा इसलिए है क्योंकि आप कुछ और गलत कर रहे हैं
एरिक होडोंस्की

1
मैं मानता हूँ कि यदि आपके सभी श्रोता रिएक्ट के माध्यम से जुड़े हैं, तो यह सही तरीका है, लेकिन यहाँ यह सवाल नहीं है।
बेन मोशर

यह सिर्फ मेरे लिए है ... मैं हमेशा किसी के साथ काम करने के बजाय सही तरीके के सही उपयोग को प्रोत्साहित करूंगा, जिससे भविष्य में उन्हें दुःख हो सकता है क्योंकि उनके पास एक समस्या का 'समाधान' है।
एरिक होडोंस्की

0

के window.addEventListenerबजाय एक त्वरित समाधान का उपयोग कर रहा है document.addEventListener

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.