Reactjs 如何侦听组件外部的单击事件

Reactjs 如何侦听组件外部的单击事件,reactjs,Reactjs,我想在下拉组件外单击时关闭下拉菜单 如何做到这一点?使用生命周期方法向文档中添加和删除事件侦听器 React.createClass({ handleClick:函数(e){ if(this.getDOMNode().包含(e.target)){ 返回; } }, componentWillMount:函数(){ document.addEventListener('click',this.handleClick,false); }, componentWillUnmount:函数(){ doc

我想在下拉组件外单击时关闭下拉菜单


如何做到这一点?

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

React.createClass({
handleClick:函数(e){
if(this.getDOMNode().包含(e.target)){
返回;
}
},
componentWillMount:函数(){
document.addEventListener('click',this.handleClick,false);
},
componentWillUnmount:函数(){
document.removeEventListener('click',this.handleClick,false);
}
});

查看此组件的第48-54行:

查看事件的目标,如果事件直接位于组件或该组件的子组件上,则单击位于内部。否则它就在外面

React.createClass({
单击文档:功能(e){
var component=React.findDOMNode(此.refs.component);
if(e.target==component | |$(component).has(e.target.length){
//组件的内部。
}否则{
//组件外部。
}
},
componentDidMount:function(){
$(document.bind('click',this.clickDocument));
},
componentWillUnmount:function(){
$(文档).unbind('click',this.clickDocument));
},
render:function(){
返回(
...
)
}
});
如果要在许多组件中使用,则使用mixin会更好:

var ClickMixin={
_单击文档:功能(e){
var component=React.findDOMNode(此.refs.component);
if(e.target==component | |$(component).has(e.target.length){
点击此按钮。点击内部(e);
}否则{
点击外部(e);
}
},
componentDidMount:函数(){
$(文档).bind('单击',此。\ u单击文档);
},
componentWillUnmount:函数(){
$(文档)。解除绑定('单击',此。\ u单击文档);
},
}

请参见此处的示例:

在我添加的元素中
mousedown
mouseup
如下所示:

onMouseDown={this.props.onMouseDown}onMouseUp={this.props.onMouseUp}
然后在父级中,我执行以下操作:

componentDidMount:function(){
window.addEventListener('mousedown',this.pageClick,false);
},
页面点击:功能(e){
if(this.mouseIsDownOnCalendar){
返回;
}
这是我的国家({
肖卡尔:错
});
},
mouseDownHandler:函数(){
this.mouseIsDownOnCalendar=true;
},
鼠标句柄:函数(){
this.mouseIsDownOnCalendar=false;
}
showCal
是一个布尔值,当
true
在我的例子中显示日历时,
false
将其隐藏

  • 创建一个覆盖整个屏幕的固定层(
    .background
  • 将目标元素(
    .target
    )置于
    .background
    元素之外,并具有更大的堆叠索引(
    z-index
  • 然后单击
    .background
    元素将被视为“在
    .target
    元素之外”

    。单击覆盖{
    位置:固定;
    左:0;
    右:0;
    排名:0;
    底部:0;
    z指数:1;
    }
    .目标{
    位置:相对位置;
    z指数:2;
    }
    
    • 以下是一个例子:
    • 有关讨论的更多信息:

    对于您的特定用例,当前接受的答案有点过度设计。如果您想在用户从下拉列表中单击时监听,只需使用
    组件作为父元素,并向其附加
    onBlur
    处理程序

    这种方法唯一的缺点是,它假设用户已经保持对元素的关注,并且它依赖于表单控件(如果考虑到
    选项卡
    键也会聚焦和模糊元素,那么表单控件可能是您想要的,也可能不是),但这些缺点实际上只是对更复杂用例的限制,在这种情况下,可能需要更复杂的解决方案

     var Dropdown = React.createClass({
    
       handleBlur: function(e) {
         // do something when user clicks outside of this element
       },
    
       render: function() {
         return (
           <select onBlur={this.handleBlur}>
             ...
           </select>
         );
       }
     });
    
    var Dropdown=React.createClass({
    把手:功能(e){
    //当用户在该元素之外单击时执行某些操作
    },
    render:function(){
    返回(
    ...
    );
    }
    });
    
    我已经为源于组件外部的事件编写了一个通用事件处理程序

    实现本身很简单:

    • 安装组件时,事件处理程序会附加到
      窗口
      对象
    • 当事件发生时,组件将检查事件是否源自组件内部。如果没有,则会在目标组件上触发onOutsideEvent
    • 卸载组件时,事件处理程序将被取消激活
    从“React”导入React;
    从“react dom”导入react dom;
    /**
    *@param{ReactClass}以定义`onOutsideEvent`处理程序的组件为目标。
    *@param{String[]}支持事件一系列有效的DOM事件名称。默认值:['mousedown']。
    *@return{ReactClass}
    */
    导出默认值(目标,supportedEvents=['mousedown'])=>{
    返回类ReactOutsideEvent扩展React.Component{
    componentDidMount=()=>{
    如果(!this.refs.target.onOutsideEvent){
    抛出新错误('组件未定义“onOutsideEvent”方法');
    }
    supportedEvents.forEach((eventName)=>{
    addEventListener(eventName,this.handleEvent,false);
    });
    };
    组件将卸载=()=>{
    supportedEvents.forEach((eventName)=>{
    removeEventListener(eventName,this.handleEvent,false);
    });
    };
    handleEvent=(事件)=>{
    让目标,,
    目标元素,
    伊森赛德,
    等外侧;
    
    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>
        );
    }
    
    npm install --save react-onclickoutside
    
    var Component = React.createClass({
      mixins: [
        require('react-onclickoutside')
      ],
      handleClickOutside: function(evt) {
        // ...handling code goes here... 
      }
    });
    
    /* 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>
        )
    }
    
    ...
    
    <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
    }
    
    <Modal onHide={this.closeFunction}>
    ...
    </Modal>