구성 요소 외부에있는 클릭 이벤트를 수신하는 방법
드롭 다운 구성 요소 외부에서 클릭이 발생하면 드롭 다운 메뉴를 닫고 싶습니다.
어떻게하나요?
추가 한 요소에서 다음 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
가죽 그것.
수명주기 메서드를 사용하여 문서에 이벤트 리스너를 추가 및 제거합니다.
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/
특정 사용 사례의 경우 현재 허용되는 대답은 약간의 과잉 엔지니어링입니다. 사용자가 드롭 다운 목록을 클릭 할 때 수신 대기하려면 <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>
);
}
});
컴포넌트 외부에서 발생하는 이벤트에 대한 일반 이벤트 핸들러 인 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']);
I voted up one of the answers even though it didn't work for me. It ended up leading me to this solution. I changed the order of operations slightly. I listen for mouseDown on the target and mouseUp on the target. If either of those return TRUE, we don't close the modal. As soon as a click is registered, anywhere, those two booleans { mouseDownOnModal, mouseUpOnModal } are set back to 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>
);
}
This has the advantage that all the code rests with the child component, and not the parent. It means that there's no boilerplate code to copy when reusing this component.
- Create a fixed layer that spans the whole screen (
.backdrop
). - Have the target element (
.target
) outside the.backdrop
element and with a greater stacking index (z-index
).
Then any click on the .backdrop
element will be considered "outside of the .target
element".
.click-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
}
.target {
position: relative;
z-index: 2;
}
- Here is an example: http://jsfiddle.net/LHmwd/
- More on the discussion: https://github.com/facebook/react/issues/579
You could use ref
s to achieve this, something like the following should work.
Add the ref
to your element:
<div ref={(element) => { this.myElement = element; }}></div>
You can then add a function for handling the click outside of the element like so:
handleClickOutside(e) {
if (!this.myElement.contains(e)) {
this.setState({ myElementVisibility: false });
}
}
Then finally, add and remove the event listeners on will mount and will unmount.
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
}
Super late to the party, but I've had success with setting a blur event on the parent element of the dropdown with the associated code to close the dropdown, and also attaching a mousedown listener to the parent element that checks if the dropdown is open or not, and will stop the event propagation if it is open so that the blur event won't be triggered.
Since the mousedown event bubbles up this will prevent any mousedown on children from causing a blur on the parent.
/* 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() shouldn't have to be called as far as I can reason but firefox doesn't play nice without it for whatever reason. Works on Chrome, Firefox, and Safari.
I found a simpler way about this.
You just need to add onHide(this.closeFunction)
on the modal
<Modal onHide={this.closeFunction}>
...
</Modal>
Assuming you have a function to close the modal.
Use the excellent react-onclickoutside mixin:
npm install --save react-onclickoutside
And then
var Component = React.createClass({
mixins: [
require('react-onclickoutside')
],
handleClickOutside: function(evt) {
// ...handling code goes here...
}
});
'program story' 카테고리의 다른 글
iOS 푸시 알림은 어떻게 작동합니까? (0) | 2020.09.16 |
---|---|
Phonegap 프로젝트에 앱 아이콘을 추가하는 방법은 무엇입니까? (0) | 2020.09.16 |
C #을 사용하여 Windows Form에 파일 찾아보기 단추를 추가하는 방법 (0) | 2020.09.16 |
Java 7 try-with-resources를 올바르게 사용하고 있습니까? (0) | 2020.09.16 |
MongoDB에서 '좋지 않음'연산자를 어떻게 사용할 수 있습니까? (0) | 2020.09.16 |