React和jQuery事件处理程序以错误的顺序触发 [英] React and jQuery event handler's fired in wrong order

查看:79
本文介绍了React和jQuery事件处理程序以错误的顺序触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建显示在屏幕顶部的菜单。当用户点击其中一个菜单项div时会出现很多链接。我不能通过点击另一个菜单项(没问题,已经实现它)来隐藏这个div,而且还可以点击其他任何地方然后点击这个div和menuitems。

I'm creating menu that appears at the top of the screen. When user clicks one of menu items div with a lot of links appear. I wan't to be able to hide this div by clicking another menu item (no problem, already implemented it) but also by clicking anywhere else then this div and menuitems.

我听说过两个解决方案:

I heard about two solutions:


  • 显示菜单后面的隐形div并覆盖整个屏幕
    并添加点击处理程序它。

  • 将事件处理程序附加到document.body。

第一个不适合我,因为该div将覆盖页面上的链接,我希望它们可以点击,即使在点击menuitem后它出现了相应的div。所以我尝试了第二次灵魂。但问题是在我的组件的处理程序之前触发了body上的jquery click处理程序。我不知道如何让它首先调用我的组件处理程序,然后阻止事件传播。

First one is not good for me because that div will cover links that are on the page and I want them to be clickable even after menuitem is clicked and it's corresponding div appeared. So I tried second soultion. But the problem is that jquery click handler on body is fired before my component's handler. I have no idea how to make it first call my components handler and then prevent event propagation.

这是代码和js小提琴:

Here is the code and js fiddle:

/** @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/

启动控制台,然后运行它以解释问题

startup console before you run it for explanation of problem

推荐答案

所以我解决了。
使用jQuery向文档添加事件处理程序时,首先触发此事件处理程序。所以你无法捕捉事件并阻止它的传播。但是当你使用document.addEventlistener附加处理程序时,这个处理程序最后被调用,你有机会反应:)点击React组件。

So I solved it. When you add event handler to document using jQuery this event handler is fired first. So you can't catch event and stop it's propagation. But when you attach handler with document.addEventlistener this handler is being called last and you have opportunity to react :) to click in React components.

我修改了Mike的代码来制作它工作( http://jsfiddle.net/s8hmstzz/ ):

I modified Mike's code to make it work (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更改事件处理程序的触发顺序。

Start console and then click div, anchor and body to see how it works. I don't know why using addEventListener instead of jQuery changes order of event handlers fired.

这篇关于React和jQuery事件处理程序以错误的顺序触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆