我创建了一个移动下拉菜单,可根据状态切换打开和关闭。一旦打开,我希望用户能够通过点击ul之外的任何地方来关闭下拉列表。
我将ul上的tabIndex属性设置为0,这给出了ul“焦点”。我还在ul中添加了一个onBlur事件,触发隐藏ul的状态更改(dropdownExpanded = false)。
<ul tabIndex="0" onBlur={this.hideDropdownMenu}>
<li onClick={this.handlePageNavigation}>Page 1</li>
<li onClick={this.handlePageNavigation}>Page 2</li>
<li onClick={this.handlePageNavigation}>Page 3</li>
</ul>
但是,当我实现此修复时,我在每个li元素上的onClick事件都无法触发。
我知道事件正在冒泡,但我对如何修复它感到很失望。有人可以帮忙吗?
注:
我知道你可以创建一个跨越整个视口的ul下方的透明div,然后只添加一个onClick甚至可以改变状态的div,但我读到了这个tabIndex / focus解决方案on Stack Overflow和我真的很想让它发挥作用。
这是一个更完整的代码视图(下拉列表是供用户选择他们的国家,更新ui):
const mapStateToProps = (state) => {
return {
lang: state.lang
}
}
const mapDispatchToProps = (dispatch) => {
return { actions: bindActionCreators({ changeLang }, dispatch) };
}
class Header extends Component {
constructor() {
super();
this.state = {
langListExpanded: false
}
this.handleLangChange = this.handleLangChange.bind(this);
this.toggleLangMenu = this.toggleLangMenu.bind(this);
this.hideLangMenu = this.hideLangMenu.bind(this);
}
toggleLangMenu (){
this.setState({
langListExpanded: !this.state.langListExpanded
});
}
hideLangMenu (){
this.setState({
langListExpanded: false
});
}
handleLangChange(e) {
let newLang = e.target.attributes['0'].value;
let urlSegment = window.location.pathname.substr(7);
// blast it to shared state
this.props.actions.changeLang( newLang );
// update browser route to change locale, but stay where they are at
browserHistory.push(`/${ newLang }/${ urlSegment }`);
//close dropdown menu
this.hideLangMenu();
}
compileAvailableLocales() {
let locales = availableLangs;
let selectedLang = this.props.lang;
let markup = _.map(locales, (loc) => {
let readableName = language[ selectedLang ].navigation.locales[ loc ];
return (
<li
key={ loc }
value={ loc }
onMouseDown={ this.handleLangChange }>
{ readableName }
</li>
);
});
return markup;
}
render() {
let localeMarkup = this.compileAvailableLocales();
return (
<section className="header row expanded">
< Navigation />
<section className="locale_selection">
<button
className="btn-locale"
onClick={this.toggleLangMenu}>
{this.props.lang}
</button>
<ul
className={this.state.langListExpanded ? "mobile_open" : " "}
value={ this.props.lang }
tabIndex="0"
onBlur={this.hideLangMenu}>
>
{ localeMarkup }
</ul>
</section>
</section>
)
}
}
答案 0 :(得分:9)
尝试使用onMouseDown而不是onClick。
答案 1 :(得分:0)
关键是onBlur触发了重新渲染,这似乎导致浏览器不跟上onClick:https://github.com/facebook/react/issues/4210
但是,如果您检查onBlur事件,则可以找到有关正在发生的事情的一些信息,event.relatedTarget会被填充,您可以使用这些信息来检测onBlur何时真正由onClick触发并进行链结。 / p>
答案 2 :(得分:0)
我只是遇到了一系列面包屑链接,其中onBlur处理程序导致了重新渲染,从而阻止了链接点击的工作。实际的问题是react每次都会重新生成链接元素,因此当它重新呈现时,它从鼠标下方交换了链接,这导致浏览器忽略了点击。
解决方法是将key
属性添加到我的链接中,以便react可以重用相同的DOM元素。
<ol>
{props.breadcrumbs.map(crumb => (
<li key={crumb.url}>
<Link to={crumb.url} >
{crumb.label}
</Link>
</li>
))}
</ol>