드롭 다운 구성 요소 외부에서 클릭이 발생하면 드롭 다운 메뉴를 닫고 싶습니다.
어떻게하나요?
답변:
추가 한 요소에서 다음 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()
입니다. 이벤트를 즉시 호출해야 하거나 React의 전처리가 방해하는 네이티브 Android 동작이 시작되기 때문입니다. 나는 그 이후로 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/91dc0129a1f6077bef57ea4ad9a860be0c600e9d/app/component/tube-tracker.jsx#L48-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>
)
}
});
이것이 많은 구성 요소에서 사용되는 경우 mixin을 사용하면 더 좋습니다.
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
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 또한 사업부와 함께 작동 tabIndex
속성
컴포넌트 외부에서 발생하는 이벤트에 대한 일반 이벤트 핸들러 인 react-outside-event를 작성했습니다 .
구현 자체는 간단합니다.
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']);
나는 그것이 나를 위해 작동하지 않았지만 대답 중 하나에 투표했습니다. 결국 저를이 솔루션으로 이끌었습니다. 작업 순서를 약간 변경했습니다. 나는 target에서 mouseDown을, target에서 mouseUp을 듣습니다. 둘 중 하나가 TRUE를 반환하면 모달을 닫지 않습니다. 클릭이 등록 되 자마자 어디에서나 두 부울 {mouseDownOnModal, mouseUpOnModal}이 다시 false로 설정됩니다.
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
것과 관련하여 오류가 발생할 수 있습니다 . 그렇지 않으면 Uncaught ReferenceError가 발생합니다. handleClickOutside가 정의되지 않았습니다 .document.addEventListener()
this
componentWillMount()
파티에 너무 늦었지만 드롭 다운을 닫는 관련 코드로 드롭 다운의 부모 요소에 흐림 이벤트를 설정하고 드롭 다운이 열려 있는지 확인하는 부모 요소에 mousedown 리스너를 연결하는 데 성공했습니다. 이벤트가 열려 있으면 이벤트 전파를 중지하여 흐림 이벤트가 트리거되지 않습니다.
mousedown 이벤트가 거품을 일으키기 때문에 자식에 대한 mousedown이 부모에게 흐려지는 것을 방지합니다.
/* 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 ()는 내가 추론 할 수있는 한 호출 할 필요는 없지만 파이어 폭스는 어떤 이유로 든 그것 없이는 잘 플레이되지 않습니다. Chrome, Firefox 및 Safari에서 작동합니다.
뛰어난 react-onclickoutside mixin을 사용하세요 .
npm install --save react-onclickoutside
그리고
var Component = React.createClass({
mixins: [
require('react-onclickoutside')
],
handleClickOutside: function(evt) {
// ...handling code goes here...
}
});