所以,我有一个自定义搜索和选择组件,用于呈现包含在父容器中的输入和结果列表:
<div className='wrapper'>
<input />
<div className='results'>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
</div>
</div>
我想要实现的是,当用户关注input
时,会显示结果列表div。我是通过一个州 - isExpanded
实现这一目标的。所以,我使用输入的onFocus方法:
<input onFocus={this.handleFocus} />
功能:
handleFocus = () => {
this.setState({
isExpanded: true
});
}
这很有效。我遇到的问题是在适当的时候让它关闭。它只应在用户实际点击wrapper
div
之外时关闭。当我需要它保持开放时:
因此,基本上wrapper
div内的任何互动都应保持开放。
为了尝试实现这一点,我在包装器周围放了一个模糊事件:
<div className='wrapper' tabIndex='1' onBlur={this.handleBlur}> ... </div>
然后是函数
handleBlur = () => {
this.setState({
isExpanded: false
});
}
问题是,当点击某个项目或专注于输入时会消除该事件发生的焦点wrapper
,但是当我不想要它时,我无法防止它被触发
我尝试使用与document.activeElement
混合的ReactDOM.findDOMNode
来比较活动元素,但它仍无法正常工作。有什么想法吗?
以下是我尝试实现的基本示例(它使用了不同的函数绑定方法,但仍然有点):
class SearchAndSelect extends React.Component {
constructor() {
super();
this.state = {
isExpanded: false
}
this.handleBlur = this.handleBlur.bind(this);
this.handleFocus = this.handleFocus.bind(this);
}
handleBlur() {
this.setState({
isExpanded: false
})
}
handleFocus() {
this.setState({
isExpanded: true
})
}
render(){
return(
<div className='wrapper' tabIndex='1' onBlur={this.handleBlur}>
<input onFocus={this.handleFocus} />
{this.state.isExpanded && <div>Results</div>}
</div>
);
}
}
ReactDOM.render(<SearchAndSelect />, document.getElementById('container'));
&#13;
<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>
<div id="container"></div>
&#13;
答案 0 :(得分:1)
如果在发生模糊事件时鼠标在包装中发生故障,您可以说要忽略模糊。我已经使用this.ignoreBlur来表示是否应该忽略模糊 - 我没有使用状态,因为你不想要或不需要它来重新渲染。我还包括移出包装器以重置ignoreBlur,以防鼠标停止,你将永远不会获得包装器的鼠标启动事件,这将使ignoreBlur永久保持为真!
<div className='wrapper' onMouseDown={this.setIgnoreBlur} onMouseUp={this.clearIgnoreBlur} onMouseOut={this.clearIgnoreBlur} onBlur={this.handleBlur}>
<input />
<div className='results'>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
<div>Result Item</div>
</div>
</div>
setIgnoreBlur = () => {
this.ignoreBlur = true;
}
clearIgnoreBlur = () => {
this.ignoreBlur = false;
}
handleBlur = () => {
if (this.ignoreBlur) return;
this.setState({
isExpanded: false
});
}
我更新了你的小提琴:https://jsfiddle.net/jwm6k66c/2474/
答案 1 :(得分:0)
我已经做了类似的事情,我通过在下面设置了一个div来实现它:
<div className='closer' onClick={this.handleBlur...
<div className='wrapper'...
.closer:
position: absolute
width/height:100%
答案 2 :(得分:0)
此高阶组件应该可以帮助您:https://github.com/kentor/react-click-outside
见那里的例子。您需要使用它增强包装器组件,然后将this.setState({ isExpanded: false })
放入handleClickOutside()
方法。