[英]click anywhere to close dropdown in react
我在页面上有多个反应的自定义构建下拉组件。 我使用 setState 触发列表项打开
toggleDropdown = (id) => {
this.setState(prevState => ({
[`dropdown${name}`]: !prevState[`dropdown${id}`] //dropdownA, dropdownB, dropdownC and so on
}))
}
如果在菜单打开时单击下拉菜单,这也将切换它。 但是后来我有更多的下拉列表,如果我打开一个下拉列表,其他下拉列表将不会关闭,如何解决这个问题? 我在 componentWillMount 中使用了一种“hacky”方式与 jquery 混合反应,在 body 上绑定单击事件,检查下拉项是否可见,如果是,则关闭它。
我的问题是,有没有更好的做法来避免使用 jquery?
我的建议是您使用合成事件onFocus
和onBlur
来触发打开/关闭状态。 onFocus
将在元素被点击时触发,而onBlur
将在“非聚焦”(点击外部)时触发。 请参阅 文档。
焦点/模糊还需要tabIndex
属性/道具来处理非输入类型元素。
我可以建议查看react-select的来源以及它们如何处理聚焦/模糊。
这是一个例子,你可以在这里看到它的演示
import React from "react";
class Dropdown extends React.Component {
state = {
open: false
};
toggleDropdown() {
this.setState({ open: !this.state.open });
}
render() {
return (
<div
style={{ border: "1px solid #CCC" }}
onBlur={() => this.toggleDropdown()}
onFocus={() => this.toggleDropdown()}
tabIndex="0"
>
Dropdown
{this.state.open && (
<div>
<div>Red</div>
<div>Green</div>
<div>Blue</div>
</div>
)}
</div>
);
}
}
export default Dropdown;
您可以使用react-onclickoutside库为您抽象主体事件处理。 您只需要将您的组件包装在它们的onClickOutside
高阶组件中,该组件将在单击发生在下拉菜单之外时执行handleClickOutside
回调。 这样你就可以在所有下拉菜单中拥有一个私有的“打开”状态,而不用关心如何实现处理。
代码可能如下所示:
import React, { Component } from 'react'
import onClickOutside from 'react-onclickoutside'
class Dropdown extends Component {
constructor() {
this.state = {open: false}
}
// Method automatically executed by the library.
handleClickOutside() {
this.setState({open: false})
}
render() { ... }
}
export default onClickOutside(Dropdown)
首先,我们创建状态,打开值为 false,因此默认情况下关闭下拉列表。 然后,我们将为单击添加一个事件侦听器,该侦听器将关闭下拉列表并在关闭下拉列表后删除事件侦听器。 然后我们向按钮添加一个 onClick 事件,使用 toggleOpen() 将状态从 false 更改为 true。 然后我们将我们的内容包装在 if/or 中以检查内容是否打开:
`class Dropdown extends React.Component {
constructor() {
super();
this.state = {
open: false
}
this.toggleOpen = this.toggleOpen.bind(this);
this.toggleClosed = this.toggleClosed.bind(this);
}
toggleOpen() {
this.setState({ open: true }, () => {
document.addEventListener('click', this.toggleClosed)
})
}
toggleClosed() {
this.setState({ open: false}, () => {
document.removeEventListener('click', this.toggleClosed)
})
}
render() {
return(
<div>
<button onClick=({ this.toggleOpen })>
Dropdown
</button>
{
this.state.open
? (
<span> Dropdown</span><br /><br />
<span> content</span><br /><br />
) :
(
null
)
</div>
}
}`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.