React Modal仅点击input后才能按Escape关闭如何解决
问题根源
- 普通div元素默认无聚焦能力,只有内部可交互元素(input、button等)获得焦点后,键盘事件才会向上冒泡到父级div
- 你将
onKeyDown事件绑定在modal容器div上,只有点击内部input让聚焦落在modal内部节点树时,ESC按键事件才能被捕获,所以出现必须先点击input才能触发关闭的问题
修复方案
你采用的「在生命周期中给全局document绑定事件监听」是最通用的修复方案,注意要在组件卸载时同步移除监听,避免内存泄漏,完整实现代码如下:
// Modal组件内部逻辑 closeModalEsc(e) { // 推荐用e.key替代已废弃的keyCode,兼容性更好 if (e.key === 'Escape' || e.keyCode === 27) { this.props.closeModal(); } } componentDidMount() { document.addEventListener('keydown', this.closeModalEsc) } componentWillUnmount() { document.removeEventListener('keydown', this.closeModalEsc) } render() { const {modal, closeModal} = this.props; if (modal) { return ( {/* 移除原div上的onKeyDown绑定即可 */} <div className="modal"> <div className="modal-dialog"> <div className="modal-content"> <form action="#" onSubmit={this.onAddName}> <button className="modal-close" type="button" onClick={closeModal}> ×</button> <input placeholder="What is your name" type="text" className="form-control modal-input" onChange={this.onUpdateName} value={this.state.textName} /> <input placeholder="Your last name" type="text" className="form-control modal-input" onChange={this.onUpdateLastName} value={this.state.textLastName} /> <button className="btn btn-dark" type="submit"> Log In</button> </form> </div> </div> </div> ) } return null }
可选替代方案
如果不想使用全局监听,也可以给modal容器div添加tabIndex="-1"属性,使其支持聚焦,Modal打开时主动调用该div的focus()方法,也可以直接在div上绑定键盘事件实现ESC关闭。
内容的提问来源于stack exchange,提问作者Fedor Lyust
相关产品推荐
相关产品推荐

