我正在创建显示在屏幕顶部的菜单。当用户单击带有很多链接的菜单项div之一时。我将无法通过单击另一个菜单项(没有问题,已经实现)来隐藏此div,而且也无法通过单击该div和menuitems以外的其他任何位置来隐藏它。
我听说了两种解决方案:
第一个对我不好,因为该div会覆盖页面上的链接,我希望即使单击menuitem并出现相应的div后,它们也可以被单击。所以我尝试了第二个灵魂。但是问题在于,主体上的jquery click处理器在我组件的处理器之前被触发。我不知道如何使它首先调用我的组件处理程序,然后阻止事件传播。
这是代码和js小提琴:
/** @jsx React.DOM */ var Menu = React.createClass({ click: function(e) { console.log('component handled click - should be called before jquery one and prevent jquery handler from running at all'); e.stopPropagation(); }, render: function(){ console.log("component renders"); return ( <div> <div>| MenuItem1 | MenuItem2 | MenuItem 3 |</div> <br /> <div className="drop"> MenuItem 1 (This div appears when you click menu item) <ul> <li><a href="#" onClick={this.click}>Item 1 - when I click this I don't want document.body.click to fire</a></li> <li><a href="#" onClick={this.click}>Item 1 - when I click this I don't want document.body.click to fire</a></li> </ul> </div> </div> ); } }); React.renderComponent(<Menu />, document.getElementById("menu")); $(document).ready(function() { console.log('document is ready'); $("body").click(function() { console.log('jquery handled click - should not happen before component handled click'); }); });
http://jsfiddle.net/psonsx6j/
运行控制台之前先启动控制台以解释问题
所以我解决了。当您使用jQuery将事件处理程序添加到文档时,将首先触发该事件处理程序。因此,您无法捕获事件并阻止事件的传播。但是,当您将处理程序与document.addEventlistener附加在一起时,此处理程序将被最后调用,您将有机会做出响应:)以单击React组件。
我修改了Mike的代码以使其工作(http://jsfiddle.net/s8hmstzz/):
/** @jsx React.DOM */ var Menu = React.createClass({ getInitialState: function() { return { show: true } }, componentDidMount: function() { // when attaching with jquery this event handler is run before other handlers //$('body').bind('click', this.bodyClickHandler); document.addEventListener('click', this.bodyClickHandler); }, componentWillUnmount: function() { //$('body').unbind('click', this.bodyClickHandler); document.removeEventListener('click', this.bodyClickHandler); }, anchorClickHandler: function(e) { console.log('click on anchor - doing some stuff and then stopping propation'); e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); }, bodyClickHandler: function(e) { console.log('bodyclickhandler'); this.setState({show: false}) }, clickHandler: function(e) { // react to click on menu item }, preventEventBubbling: function(e) { console.log('click on div - stopping propagation'); e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); }, render: function() { return ( <div> <a href="#" onClick={this.anchorClickHandler}>Link - will stop propagation</a> <div id="menudrop" onClick={this.preventEventBubbling} style={{display: this.state.show ? 'block' : 'none'}}> <ul> <li onClick={this.clickHandler}>Menu Item</li> </ul> </div> </div> ) } }); React.renderComponent(<Menu />, document.getElementById('menu'));
启动控制台,然后单击div,anchor和body以查看其工作原理。我不知道为什么使用addEventListener而不是jQuery会更改触发的事件处理程序的顺序。