मैं एक ड्रॉपडाउन मेनू को बंद करना चाहता हूं जब ड्रॉपडाउन घटक के बाहर एक क्लिक होता है।
मैं उसको कैसे करू?
मैं एक ड्रॉपडाउन मेनू को बंद करना चाहता हूं जब ड्रॉपडाउन घटक के बाहर एक क्लिक होता है।
मैं उसको कैसे करू?
जवाबों:
तत्व में मैंने इसे जोड़ा है mousedown
और mouseup
इस तरह है:
onMouseDown={this.props.onMouseDown} onMouseUp={this.props.onMouseUp}
फिर माता-पिता में मैं ऐसा करता हूं:
componentDidMount: function () {
window.addEventListener('mousedown', this.pageClick, false);
},
pageClick: function (e) {
if (this.mouseIsDownOnCalendar) {
return;
}
this.setState({
showCal: false
});
},
mouseDownHandler: function () {
this.mouseIsDownOnCalendar = true;
},
mouseUpHandler: function () {
this.mouseIsDownOnCalendar = false;
}
showCal
एक बूलियन यह है कि जब true
मेरे मामले में पता चलता है एक कैलेंडर और false
यह खाल।
preventDefault()
तुरंत घटनाओं पर कॉल करने की आवश्यकता है या देशी एंड्रॉइड व्यवहार में किक करता है, जिसके साथ रिएक्ट का प्रीप्रोसेसिंग हस्तक्षेप करता है। मैंने npmjs.com/package/react-onclickoutside को लिखा है।
जीवन-चक्र के तरीकों का उपयोग करते हुए दस्तावेज़ में घटना श्रोताओं को जोड़ते हैं और हटाते हैं।
React.createClass({
handleClick: function (e) {
if (this.getDOMNode().contains(e.target)) {
return;
}
},
componentWillMount: function () {
document.addEventListener('click', this.handleClick, false);
},
componentWillUnmount: function () {
document.removeEventListener('click', this.handleClick, false);
}
});
इस घटक की रेखाएँ 48-54 की जाँच करें: https://github.com/i-like-robots/react-tube-tracker/blob/91dc0129a1f6077bef57ea4ad9a860be0cbc9d/app/component/tube-tracker.jsx#L48-5448-54
ईवेंट के लक्ष्य को देखें, यदि ईवेंट सीधे घटक या उस घटक के बच्चों पर था, तो क्लिक अंदर था। नहीं तो बाहर ही था।
React.createClass({
clickDocument: function(e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
// Inside of the component.
} else {
// Outside of the component.
}
},
componentDidMount: function() {
$(document).bind('click', this.clickDocument);
},
componentWillUnmount: function() {
$(document).unbind('click', this.clickDocument);
},
render: function() {
return (
<div ref='component'>
...
</div>
)
}
});
यदि इसे कई घटकों में उपयोग किया जाना है, तो यह एक मिश्रण के साथ अच्छा है:
var ClickMixin = {
_clickDocument: function (e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
this.clickInside(e);
} else {
this.clickOutside(e);
}
},
componentDidMount: function () {
$(document).bind('click', this._clickDocument);
},
componentWillUnmount: function () {
$(document).unbind('click', this._clickDocument);
},
}
यहां देखें उदाहरण: https://jsfiddle.net/0Lshs7mg/1/
this.refs.component
DOM तत्व का जिक्र 0.14 facebook.github.io/react/blog/2015/07/03/… के
आपके विशिष्ट उपयोग के मामले के लिए, वर्तमान में स्वीकृत उत्तर टैड ओवर-इंजीनियर है। यदि आप तब सुनना चाहते हैं जब उपयोगकर्ता ड्रॉपडाउन सूची से बाहर निकलता है, <select>
तो मूल घटक के रूप में एक घटक का उपयोग करें और एक onBlur
हैंडलर संलग्न करें ।
इस दृष्टिकोण की एकमात्र कमी यह है कि यह मानता है कि उपयोगकर्ता ने पहले से ही तत्व पर ध्यान बनाए रखा है, और यह एक प्रपत्र नियंत्रण पर निर्भर करता है (जो आप चाहते हैं या नहीं हो सकता है यदि आप खाते में लेते हैं कि tab
कुंजी भी ध्यान केंद्रित करती है और तत्वों को धुंधला करती है ) - लेकिन ये कमियां वास्तव में अधिक जटिल उपयोग के मामलों के लिए एक सीमा है, ऐसे मामले में अधिक जटिल समाधान आवश्यक हो सकता है।
var Dropdown = React.createClass({
handleBlur: function(e) {
// do something when user clicks outside of this element
},
render: function() {
return (
<select onBlur={this.handleBlur}>
...
</select>
);
}
});
onBlur
div भी div के साथ काम करता है अगर इसमें tabIndex
गुण है
मैंने उन घटनाओं के लिए एक सामान्य ईवेंट हैंडलर लिखा है, जो घटक के बाहर उत्पन्न होते हैं, प्रतिक्रिया-बाहर की घटना ।
कार्यान्वयन स्वयं सरल है:
window
ऑब्जेक्ट से जुड़ा होता है ।onOutsideEvent
लक्ष्य घटक पर ट्रिगर होता है।import React from 'react';
import ReactDOM from 'react-dom';
/**
* @param {ReactClass} Target The component that defines `onOutsideEvent` handler.
* @param {String[]} supportedEvents A list of valid DOM event names. Default: ['mousedown'].
* @return {ReactClass}
*/
export default (Target, supportedEvents = ['mousedown']) => {
return class ReactOutsideEvent extends React.Component {
componentDidMount = () => {
if (!this.refs.target.onOutsideEvent) {
throw new Error('Component does not defined "onOutsideEvent" method.');
}
supportedEvents.forEach((eventName) => {
window.addEventListener(eventName, this.handleEvent, false);
});
};
componentWillUnmount = () => {
supportedEvents.forEach((eventName) => {
window.removeEventListener(eventName, this.handleEvent, false);
});
};
handleEvent = (event) => {
let target,
targetElement,
isInside,
isOutside;
target = this.refs.target;
targetElement = ReactDOM.findDOMNode(target);
isInside = targetElement.contains(event.target) || targetElement === event.target;
isOutside = !isInside;
if (isOutside) {
target.onOutsideEvent(event);
}
};
render() {
return <Target ref='target' {... this.props} />;
}
}
};
घटक का उपयोग करने के लिए, आपको उच्च आदेश घटक का उपयोग करके लक्ष्य घटक वर्ग घोषणा को लपेटने की आवश्यकता है और उन घटनाओं को परिभाषित करें जिन्हें आप संभालना चाहते हैं:
import React from 'react';
import ReactDOM from 'react-dom';
import ReactOutsideEvent from 'react-outside-event';
class Player extends React.Component {
onOutsideEvent = (event) => {
if (event.type === 'mousedown') {
} else if (event.type === 'mouseup') {
}
}
render () {
return <div>Hello, World!</div>;
}
}
export default ReactOutsideEvent(Player, ['mousedown', 'mouseup']);
भले ही यह मेरे लिए काम न करे, मैंने एक जवाब दिया। इसने मुझे इस समाधान की ओर अग्रसर किया। मैंने संचालन के क्रम को थोड़ा बदल दिया। मैं लक्ष्य पर माउसडाउन और लक्ष्य पर माउसअप के लिए सुनता हूं। यदि उनमें से कोई भी TRUE लौटाता है, तो हम मोडल को बंद नहीं करते हैं। जैसे ही एक क्लिक पंजीकृत होता है, कहीं भी, उन दो बूलियन {mouseDownOnModal, mouseUpOnModal} को गलत पर सेट किया जाता है।
componentDidMount() {
document.addEventListener('click', this._handlePageClick);
},
componentWillUnmount() {
document.removeEventListener('click', this._handlePageClick);
},
_handlePageClick(e) {
var wasDown = this.mouseDownOnModal;
var wasUp = this.mouseUpOnModal;
this.mouseDownOnModal = false;
this.mouseUpOnModal = false;
if (!wasDown && !wasUp)
this.close();
},
_handleMouseDown() {
this.mouseDownOnModal = true;
},
_handleMouseUp() {
this.mouseUpOnModal = true;
},
render() {
return (
<Modal onMouseDown={this._handleMouseDown} >
onMouseUp={this._handleMouseUp}
{/* other_content_here */}
</Modal>
);
}
इसका यह फायदा है कि सभी कोड चाइल्ड कंपोनेंट के साथ रहते हैं, न कि पेरेंट्स के। इसका मतलब है कि इस घटक का पुन: उपयोग करते समय कॉपी करने के लिए कोई बॉयलरप्लेट कोड नहीं है।
.backdrop
)।.target
बाहर .backdrop
और अधिक स्टैकिंग इंडेक्स ( z-index
) के साथ लक्ष्य तत्व ( ) रखें।तब .backdrop
तत्व पर किसी भी क्लिक को " .target
तत्व के बाहर" माना जाएगा ।
.click-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
}
.target {
position: relative;
z-index: 2;
}
आप ref
इसे प्राप्त करने के लिए s का उपयोग कर सकते हैं , निम्नलिखित की तरह कुछ काम करना चाहिए।
ref
अपने तत्व में जोड़ें :
<div ref={(element) => { this.myElement = element; }}></div>
आप तत्पश्चात तत्व के बाहर क्लिक से निपटने के लिए एक फ़ंक्शन जोड़ सकते हैं:
handleClickOutside(e) {
if (!this.myElement.contains(e)) {
this.setState({ myElementVisibility: false });
}
}
फिर अंत में, घटना श्रोताओं को जोड़ने और हटाने पर माउंट हो जाएगा और अनमाउंट हो जाएगा।
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
handleClickOutside
में document.addEventListener()
जोड़कर this
संदर्भ। अन्यथा यह देता है Uncaught ReferenceError: handleClickOutside परिभाषित नहीं है मेंcomponentWillMount()
पार्टी के लिए सुपर देर से, लेकिन मुझे ड्रॉपडाउन के मूल तत्व पर एक धब्बा घटना सेट करने में सफलता मिली है और ड्रॉपडाउन को बंद करने के लिए संबद्ध कोड के साथ एक मूसडाउन श्रोता को संलग्न करना है जो यह जांचता है कि ड्रॉपडाउन खुला है या नहीं या नहीं, और अगर यह खुला है कि घटना के प्रसार को रोक देगा ताकि धब्बा घटना ट्रिगर नहीं होगा।
चूंकि मूसडाउन इवेंट में बुलबुले आते हैं, इसलिए यह बच्चों पर किसी भी मूसडाउन को माता-पिता पर धब्बा पैदा करने से रोकेगा।
/* Some react component */
...
showFoo = () => this.setState({ showFoo: true });
hideFoo = () => this.setState({ showFoo: false });
clicked = e => {
if (!this.state.showFoo) {
this.showFoo();
return;
}
e.preventDefault()
e.stopPropagation()
}
render() {
return (
<div
onFocus={this.showFoo}
onBlur={this.hideFoo}
onMouseDown={this.clicked}
>
{this.state.showFoo ? <FooComponent /> : null}
</div>
)
}
...
e.preventDefault () को जहां तक कारण हो सकता है, तब तक नहीं बुलाया जाना चाहिए, लेकिन फायरफॉक्स इसके बिना अच्छा नहीं लगता है। क्रोम, फ़ायरफ़ॉक्स और सफारी पर काम करता है।
मुझे इस बारे में एक सरल तरीका मिला।
आपको बस onHide(this.closeFunction)
मोडल पर जोड़ना होगा
<Modal onHide={this.closeFunction}>
...
</Modal>
मान लें कि आपके पास मोडल को बंद करने के लिए एक फ़ंक्शन है।
उत्कृष्ट प्रतिक्रिया-ऑनक्लिकआउटसाइड मिक्सिन का उपयोग करें :
npm install --save react-onclickoutside
और तब
var Component = React.createClass({
mixins: [
require('react-onclickoutside')
],
handleClickOutside: function(evt) {
// ...handling code goes here...
}
});