在鼠标悬停上打开菜单,在mouseleave上关闭菜单进行反应

时间:2017-12-28 20:24:11

标签: reactjs drop-down-menu material-ui onmouseover onmouseout

我刚开始接受电镀反应。我目前正在使用material-ui和我的navBar进行反应。当我将鼠标悬停在菜单上时,会显示下拉列表。但是为了关闭下拉列表,我必须单击下拉列表的外部。我希望能够在我将鼠标悬停在下拉菜单或移动到不同的菜单选项时关闭下拉菜单(在这种情况下,应显示不同的下拉菜单)。像这样的东西:https://www.palantir.com/

我环顾四周,但没有找到解决办法。这是我最接近的:Material-ui: open menu by event hover

我尝试使用相同的技术并将其添加到我的代码中,但无济于事。有什么建议?谢谢!

编辑:我在这里重新创建了我的问题:https://react-xmaiyw.stackblitz.io 单击“为什么我们”时可以看到问题。

 handleClick = (event) => {
 event.preventDefault();

   this.setState({
    open: true,
    anchorEl: event.currentTarget,
   });
 };

handleRequestClose = () => {
  this.setState({
   open: false,
  });
};

render() {
return (
  <FlatButton
  onClick={this.handleClick}
  onMouseOver={this.handleClick}
  onMouseLeave={this.handleRequestClose} //When I add this line of 
     //code, it keeps flickering very fast almost as if drop-down 
     //doesn't open
  label="Why Us?"
/>
)}

1 个答案:

答案 0 :(得分:5)

闪烁是由鼠标下方菜单打开引起的。当菜单打开时,鼠标不再位于按钮上方,因此它会提示mouseleave事件,关闭菜单,以便鼠标再次位于按钮上方,提示mouseenter事件,打开菜单......依此类推。

您可以通过一些额外的逻辑来完成您想要的操作,以跟踪鼠标的位置,以及确保用户有时间在按钮和菜单之间转换鼠标的超时时间。

import React from 'react';
import Button from 'material-ui/Button';
import Menu, { MenuItem } from 'material-ui/Menu';

const timeoutLength = 300;

class SimpleMenu extends React.Component {
  state = {
    anchorEl: null,

    // Keep track of whether the mouse is over the button or menu
    mouseOverButton: false,
    mouseOverMenu: false,
  };

  handleClick = event => {
    this.setState({ open: true, anchorEl: event.currentTarget });
  };

  handleClose = () => {
    this.setState({ mouseOverButton: false, mouseOverMenu: false });
  };

  enterButton = () => {
    this.setState({ mouseOverButton: true });
  }

  leaveButton = () => {
    // Set a timeout so that the menu doesn't close before the user has time to
    // move their mouse over it
    setTimeout(() => {
      this.setState({ mouseOverButton: false });
    }, timeoutLength);
  }

  enterMenu = () => {
    this.setState({ mouseOverMenu: true });
  }

  leaveMenu = () => {
     setTimeout(() => {
      this.setState({ mouseOverMenu: false });
     }, timeoutLength);
  }

  render() {
    // Calculate open state based on mouse location
    const open = this.state.mouseOverButton || this.state.mouseOverMenu;

    return (
      <div>
        <Button
          aria-owns={this.state.open ? 'simple-menu' : null}
          aria-haspopup="true"
          onClick={this.handleClick}
          onMouseEnter={this.enterButton}
          onMouseLeave={this.leaveButton}
        >
          Open Menu
        </Button>
        <Menu
          id="simple-menu"
          anchorEl={this.state.anchorEl}
          open={open}
          onClose={this.handleClose}
          MenuListProps={{
            onMouseEnter: this.enterMenu,
            onMouseLeave: this.leaveMenu,
          }}

        >
          <MenuItem onClick={this.handleClose}>Profile</MenuItem>
          <MenuItem onClick={this.handleClose}>My account</MenuItem>
          <MenuItem onClick={this.handleClose}>Logout</MenuItem>
        </Menu>
      </div>
    );
  }
}

export default SimpleMenu;

我使用MenuListProps直接在mouseEnter本身设置mouseLeaveMenuList事件,因为Menu组件包含一堆不可见(disply: none {1}})过渡元素对鼠标事件有奇怪的影响。 MenuList是实际显示的元素,因此直接在其上设置鼠标事件是有意义的。

您可能需要使用timeoutLength并进行过渡以使所有内容都变得平滑。