source

구성 요소 외부에 있는 클릭 이벤트를 수신하는 방법

ittop 2023. 3. 28. 22:37
반응형

구성 요소 외부에 있는 클릭 이벤트를 수신하는 방법

드롭다운 컴포넌트 외부에서 클릭이 발생하면 드롭다운메뉴를 닫고 싶다.

그걸 어떻게 하는 거죠?

수명 주기 방법을 사용하여 문서에 이벤트 수신기를 추가하거나 제거합니다.

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

에 the가추 in in in를 했습니다.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({
    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/

특정 사용 사례에 대해 현재 받아들여지고 있는 답변은 다소 과대 설계되어 있습니다.했을 때 수 하려면 , 「기다리다」를 합니다.<select>, 모 component an an an an an an an an an an an an an an an 를 붙입니다.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']);

나에게 효과가 없었지만, 나는 그 답 중 하나를 투표로 뽑았다.그것은 결국 나를 이 해결책으로 이끌었다.저는 작업 순서를 조금 바꿨습니다.타겟에서는 mouseDown을, 타겟에서는 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;
}
  • 다음은 예를 제시하겠습니다.http://jsfiddle.net/LHmwd/
  • 자세한 것은, https://github.com/facebook/react/issues/579 를 참조해 주세요.

사용할 수 있습니다.ref이를 실현하기 위해서는 다음과 같은 것이 필요합니다.

를 추가합니다.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
}

파티는 매우 늦었지만 드롭다운의 부모 요소에 관련 코드로 블러 이벤트를 설정하고 드롭다운이 열려 있는지 여부를 확인하는 부모 요소에 머드다운 리스너를 부착하는 데 성공했습니다.또한 이벤트 전파가 열려 있으면 이벤트 전파를 중지하여 흐림 이벤트가 트리거되지 않도록 합니다.

잔털 깎기 이벤트가 거품이 끼기 때문에 자녀에 대한 잔털 깎기가 부모에게 흐릿함을 주는 것을 방지할 수 있습니다.

/* 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.provent Default()는 가능한 한 호출할 필요가 없습니다만, 파이어폭스는 어떠한 이유로든 파이어폭스 없이는 동작하지 않습니다.Chrome, Firefox 및 Safari에서 작동합니다.

나는 이것에 대해 더 간단한 방법을 찾았다.

추가만 하면 됩니다.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... 
  }
});

언급URL : https://stackoverflow.com/questions/23821768/how-to-listen-for-click-events-that-are-outside-of-a-component

반응형