如何监听组件外部的点击事件

IT技术 reactjs
2021-05-07 00:04:26

当单击发生在下拉组件之外时,我想关闭下拉菜单。

我怎么做?

4个回答

使用生命周期方法向文档添加和删除事件侦听器。

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

在我添加的元素中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({
    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>
     );
   }
 });