我正在使用React编写自动完成功能,当用户选择列表中的项目时,我希望输入更新。我的问题是当输入失去焦点时我希望菜单消失,除非用户在菜单中选择。目前,显示菜单基于名为showDropDown的属性。在render方法中我有showDropDown它构建菜单组件。似乎在菜单项上的单击侦听器之前调用了render方法,并且在调用onClick之前将其删除。
handleOnBlur = () => {
this.setState({ showDropDown: false });
};
handleOnFocus = () => {
this.setState({ showDropDown: true });
};
handleRenderSubComponents = (options) => {
...
return options.map((option) => {
...
return (<li key={displayString} className={className}>
<span onClick={() => {this.handleOnItemSelect(option, fieldInput);}} style={{ cursor: 'pointer' }}>
{displayString}
</span>
</li>);
});
};
render() {
...
return (
<div className={className}>
<div>
<input
style={{ position: 'relative' }}
disabled={disabled}
ref={(inputElem) => {this.inputElem = inputElem;}}
valueLink={{ value: this.state.value, requestChange: (value) => this.handleOnChange(value) }}
onBlur={this.handleOnBlur}
onFocus={this.handleOnFocus}
onKeyUp={this.handleOnKeyUp}
/>
</div>
<ul className="dropdown-menu dropdown-menu-justify" style={dropDownStyle} >
{showDropDown && this.handleRenderSubComponents(options)}
</ul>
</div>
);
}
如果输入失去焦点但焦点不在菜单中,我需要做的只是隐藏菜单
答案 0 :(得分:0)
我认为这可以满足您的需求。关键是容器上的onMouseDown事件在输入的onBlur之前被触发。所以我们设置了一个可以在onBlur中检查的类变量,如果单击了容器,我们强制焦点回到输入。 setTimeout再次清除此变量,因此执行顺序为onMouseDown,onBlur,setTimeout回调。
class App extends React.Component {
constructor(props) {
super(props);
this.onInputChange = this.onInputChange.bind(this);
this.onInputBlur = this.onInputBlur.bind(this);
this.onContainerMouseDown = this.onContainerMouseDown.bind(this);
this.onOptionClick = this.onOptionClick.bind(this);
this.state = {
input: '',
showList: false
};
this.options = ['Option 1', 'Option 2', 'Option 3', 'Option 4'];
}
componentWillUnmount() {
clearTimeout(this.containerMouseDownTimeout);
}
onInputChange(e) {
this.setState({input: e.target.value, showList: e.target.value.length > 2});
}
onInputBlur() {
const showList = this.clickedInContainer && this.state.input.length > 2;
this.setState({
showList
});
if (showList) {
this.input.getDOMNode().focus();
}
}
onContainerMouseDown() {
this.clickedInContainer = true;
this.containerMouseDownTimeout = setTimeout(() => {
this.clickedInContainer = false;
});
}
onOptionClick(option) {
this.setState({
input: option,
showList: false
})
}
renderList() {
return (
<ol style={{cursor: 'pointer'}}>
{this.options.map((o, i) => <li key={i} onClick={() => this.onOptionClick(o)}>{o}</li>)}
</ol>);
}
render() {
return (
<div onMouseDown={this.onContainerMouseDown}>
<input ref={ref => this.input = ref} value={this.state.input}
onChange={this.onInputChange} onBlur={this.onInputBlur}/>
{this.state.showList && this.renderList()}
</div>
)
}
}
React.render(<App />, document.getElementById('container'));