태그 보관물: reactjs

reactjs

구성 요소 외부에있는 클릭 이벤트를 수신하는 방법 외부에서 클릭이 발생하면 드롭 다운 메뉴를 닫고

드롭 다운 구성 요소 외부에서 클릭이 발생하면 드롭 다운 메뉴를 닫고 싶습니다.

어떻게하나요?



답변

추가 한 요소에서 다음 mousedownmouseup같이합니다.

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']);

답변

나는 그것이 나를 위해 작동하지 않았지만 대답 중 하나에 투표했습니다. 결국 저를이 솔루션으로 이끌었습니다. 작업 순서를 약간 변경했습니다. 나는 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>
    );
}

이것은 모든 코드가 부모가 아닌 자식 구성 요소에 있다는 이점이 있습니다. 이는이 컴포넌트를 재사용 할 때 복사 할 상용구 코드가 없음을 의미합니다.


답변

  1. 전체 화면 ( .backdrop)에 걸쳐있는 고정 레이어를 만듭니다 .
  2. 대상 요소 ( .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;
}