[英]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.js
和bootstrap.js
文件,并仅保留了bootstrap.css
。
我使用state
来显示/隐藏<ul>
列表(我将其设置为display: block
以覆盖默认display: none
of bootstrap.css
)。
我已经设置了2个主要的处理程序,用于显示和隐藏每个项目的onclick
的<ul>
和1个处理程序:
toggleShow()
- 在附加到按钮的onBlur
的state
切换show
属性。 hide()
- 通过状态隐藏<ul>
(它还会做一件我要解释的事情)。 doSomething()
- 点击一个项目时会触发。 这种情况有一个很好的挑战,当我们隐藏<ul>
我们无法处理click事件。
但为什么?
因为我们并没有真正隐藏它,所以当state.show
为false时它不会被渲染。 所以基本上有一种setState
的竞争条件触发了对doSomething
事件处理程序的处理程序的重新渲染,该处理程序无法运行。
因此,这里的挑战是确定触发按钮的onBlur
事件的活动元素是否是<ul>
的项目。 如果是,那么我们需要让项目触发它的onClick
事件,然后才设置状态并“隐藏”。
我们在附加到event
的relatedTarget
的帮助下完成了这项工作。 这是我们正在寻找的活动元素,如果我们有一个并且它不是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.