在reactjs中切换下拉菜单

时间:2015-05-09 02:37:44

标签: javascript drop-down-menu toggle reactjs

我的导航栏上有一个简单的下拉菜单,代码如下:https://jsfiddle.net/jL3yyk98/10/

的index.html

<div id="menu-button"></div>

NavMenu.js

var NavMenu = React.createClass({
    getDefaultProps: function()
    {
        return {
            isOpen: false
        };
    },

    render: function()
    {
        if (this.props.isOpen)
        {
            return (
                <div className="dropdown">
                    <ul>
                        <li><a href="#">News</a></li>
                        <li><a href="#">About</a></li>
                        <li><a href="#">Guidelines</a></li>
                        <li><a href="#">Exchange</a></li>
                        <li><a href="#">Forum</a></li>
                    </ul>
                </div>
            );
        }
        return null;
    }
});

NavMenuButton.js

var NavMenuButton = React.createClass({

    getInitialState: function()
    {
        return {
            isOpen: false
        };
    },

    toggleMenu: function(e)
    {
        e.stopPropagation();
        this.setState({isOpen: !this.state.isOpen});
    },

    onClose: function()
    {
        this.setState({isOpen: false});
    },

    componentDidMount: function ()
    {
        document.body.addEventListener('click', this.onClose);
    },

    componentWillUnmount: function ()
    {
        document.body.removeEventListener('click', this.onClose);
    },

    render: function()
    {
        return (
            <div>
                <a onClick={this.toggleMenu} href="#">Menu</a>
                <NavMenu isOpen={this.state.isOpen} />
            </div>
        );
    }

});

React.render(<NavMenuButton />, document.getElementById('menu-button'));

我理解当前的代码,当用户单击菜单按钮关闭菜单时,调用toggleMenu方法和onClose方法(因为它们也有效地单击了主体);并且首先调用onClose方法,这意味着将状态设置为false,然后调用toggleMenu方法并将其设置回true。为什么会这样,以及如何修复它以便单击菜单按钮切换菜单点击正文隐藏菜单?

如果这种方法出现错误,我应该使用哪种方法?我的反应相当新,所以我仍然在学习什么地方和原因。

另外,我不能使用全身div作为解决方案,它需要是一个典型的下拉列表;因此,如果用户想要与页面的其他部分进行交互(可能点击链接),那么他们就可以这样做。

2 个答案:

答案 0 :(得分:3)

您的问题是,点击该链接也会调用正文点击监听器。这意味着您的州将来自:

  1. 点击链接
  2. 点击名为
  3. 的正文上的侦听器
  4. This.state.open设为false
  5. 使用this.state.open false
  6. 调用渲染
  7. 点击名为
  8. 的链接上的监听器
  9. This.state.open设为true
  10. 使用this.state.open true
  11. 调用渲染

    e.stopPropagation()在React中不起作用。一个解决方法是:

    handleBodyClick: function(e)
    {
        if (e.target.nodeName !== 'A') {
           this.setState({isOpen: false});
        }
    },
    

    另一种方式(更好的方法)是让点击侦听器不在主体上,而是在div上,并使其尽可能大(基本上与主体的大小相同)。

    以下是绑定div而不是body 的示例:https://jsfiddle.net/jL3yyk98/

答案 1 :(得分:0)

handleClose: function() {
  this.setState({isOpen: false});
},

handleGlobalClick: function(event) {
  var _con = this.refs.mC.getDOMNode() // <component ref="mC">
  if (!(_con == event.target) && !_con.contains(event.target)) {
    this.handleClose();
  }
},

componentDidMount: function() {
  document.body.addEventListener('click', this.handleGlobalClick);
},

componentWillUnmount: function() {
  document.body.removeEventListener('click', this.handleGlobalClick);
},

这个关于最新chrome的工作,你也可以使用jQuery重写node.contains()