繁体   English   中英

在菜单区域外单击或悬停时关闭反应按钮下拉菜单

[英]Close react button dropdown menu on clicking or hovering outside of menu area

在我的 React 应用程序中,其中一个组件正在创建一个按钮下拉菜单,如下所示。

<div class="dropdown">
    <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
    <span class="caret"></span></button>
    <ul class="dropdown-menu">
      <li><a onClick=doSomething href="#">HTML</a></li>
      <li><a onClick=doSomething href="#">CSS</a></li>
      <li><a onClick=doSomething href="#">JavaScript</a></li>
    </ul>   
</div>

如果有人单击/悬停此菜单区域之外的任何位置,我该如何关闭此菜单?

不要在你的React中使用jQuery事件和DOM操作,你错过了这一点。
你有一个state使用它!

在下面的示例中,您可以看到我删除了所有jquery.jsbootstrap.js文件,并仅保留了bootstrap.css
我使用state来显示/隐藏<ul>列表(我将其设置为display: block以覆盖默认display: none of bootstrap.css )。
我已经设置了2个主要的处理程序,用于显示和隐藏每个项目的onclick<ul>和1个处理程序:

  1. toggleShow() - 在附加到按钮的onBlurstate切换show属性。
  2. hide() - 通过状态隐藏<ul> (它还会做一件我要解释的事情)。
  3. doSomething() - 点击一个项目时会触发。

这种情况有一个很好的挑战,当我们隐藏<ul>我们无法处理click事件。

但为什么?

因为我们并没有真正隐藏它,所以当state.show为false时它不会被渲染。 所以基本上有一种setState的竞争条件触发了对doSomething事件处理程序的处理程序的重新渲染,该处理程序无法运行。
因此,这里的挑战是确定触发按钮的onBlur事件的活动元素是否是<ul>的项目。 如果是,那么我们需要让项目触发它的onClick事件,然后才设置状态并“隐藏”。
我们在附加到eventrelatedTarget的帮助下完成了这项工作。 这是我们正在寻找的活动元素,如果我们有一个并且它不是null那么我们触发它的click事件(不管它是什么元素,我们不关心的方式),然后我们才设置show: false状态show: false

一个工作的例子:

 class DropDown extends React.Component{ constructor(props){ super(props); this.state = { show: false } this.doSomething = this.doSomething.bind(this); this.toggleShow = this.toggleShow.bind(this); this.hide = this.hide.bind(this); } doSomething(e){ e.preventDefault(); console.log(e.target.innerHTML); } toggleShow(){ this.setState({show: !this.state.show}); } hide(e){ if(e && e.relatedTarget){ e.relatedTarget.click(); } this.setState({show: false}); } render(){ return( <div className="dropdown"> <button className="btn btn-primary dropdown-toggle" type="button" onClick={this.toggleShow} onBlur={this.hide} > {"Dropdown Example"} <span className="caret"></span> </button> { this.state.show && ( <ul className="dropdown-menu" style={{display: 'block'}}> <li><a onClick={this.doSomething} href="#">HTML</a></li> <li><a onClick={this.doSomething} href="#">CSS</a></li> <li><a onClick={this.doSomething} href="#">JavaScript</a></li> </ul> ) } </div> ); } } ReactDOM.render(<DropDown />, document.getElementById('root')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <div id="root"></div> 

有几种方法可以做到这一点。 最简单的方法是让事件监听器监听click事件或为dropdown组件编写onBlur函数。

  componentWillMount() {
    document.body.addEventListener('click', this.handleClick);
  }

  componentWillUnmount() {
    document.body.removeEventListener('click', this.handleClick);
  }

然后你必须将你的组件包装在监听器组件中。

这是工作的JS小提琴。 https://jsfiddle.net/vamshikrishna144/zukcpfr2/

onBlur = {() => console.log("Clicked outside")}

在 Dropdown 外部单击时会触发上述方法。 您可以更改状态等以显示或隐藏您的 div 或反应下拉列表

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM