我正在尝试模仿一个标题,如果您单击下拉菜单,它将显示弹出菜单,并且在单击弹出菜单元素之外时,它会在标题中的多个元素中消失。
这是我修改过的普通笔,但无法使其正常工作: https://codepen.io/anon/pen/JOGGzL
handleClick() {
if (!this.state.popupVisible) {
document.addEventListener('click', this.handleOutsideClick, false);
} else {
document.removeEventListener('click', this.handleOutsideClick, false);
}
this.setState(prevState => ({
popupVisible: !prevState.popupVisible,
}));
}
handleOutsideClick(e) {
if (this.node.contains(e.target)) {
return;
}
this.handleClick();
}
我尝试创建唯一的引用并通过handleClick和handleOutsideClick传入参数来区分两个不同的弹出按钮,但我遇到了一个问题,它似乎产生了很多EventListeners而没有正确删除它们.
一次切换一个按钮并在用户单击任一弹出元素外部时停用所有按钮的最优雅的方法是什么?我是否必须创建单独的组件来处理这个问题?
谢谢
最佳答案
您可以使用 React 的生命周期方法,而不是在实际处理程序中添加和删除事件:
componentDidMount() {
document.addEventListener('click', this.handleOutsideClick);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleOutsideClick);
}
您的handleOnClick方法可以执行标准切换状态的操作,但是如果它不是下拉列表或包含目标,则handleOutsideClick可以始终将其设置为false:
handleOutsideClick(event) {
if (this.node === event.target || !this.node.contains(event.target)) {
this.setState(prevState => ({
popupVisible: false
}));
}
}
处理多个弹出窗口的最优雅的方法是使用一个类来执行您在上面看到的所有逻辑,称为 Popover,该类呈现子组件。您可以在父组件中重用它,如下所示:
const MorePops = () => (
<div>
<Popover label={'label text'}>
<div>{'Child'}</div>
</Popover>
<Popover label={'label text'}>
<div>{'Child'}</div>
</Popover>
<Popover label={'label text'}>
<div>{'Child'}</div>
</Popover>
<Popover label={'label text'}>
<div>{'Child'}</div>
</Popover>
</div>
);
关于javascript - React 处理多个元素外部的点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47079171/