【问题标题】:Material UI Menu with subitems won't close whole menu带有子项的 Material UI 菜单不会关闭整个菜单
【发布时间】:2020-01-30 14:58:20
【问题描述】:

我有一个带有自定义 MenuItem 的 Material UI 菜单组件。现在,当打开菜单和子菜单时,我希望能够在单击菜单外部时关闭整个菜单。我仍然需要单击两次,首先关闭子菜单,然后关闭实际菜单。

文档MUI menu 是指使用anchorEl 作为boolean 来确定菜单是否打开,但即使我从自定义菜单项发送关闭回调函数,它也只会在单击时使用handleClose() 自行关闭组件之外。因此,在所附图片中,仅包含 Corporate Finance 的 Container 已关闭,菜单也未关闭。

无法理解,因为anchorElcloseFunction 中变为null,核心菜单仍然保持打开状态。尝试使用基于 Modal 组件构建的菜单和 MenuItems 和 Popover。

MenuComponent

const MoreMenu = ({
  userTagData,
  onChangeItemName,
  selectedTags,
  onTagSelected,
  onRemoveItem,
  data,
  item,
}) => {
  const [anchorEl, setAnchorEl] = useState(null);
  const [subMenuPopUpName, setSubMenuPopUpName] = useState('');


  const renderChangeTitlePopUp = () => (
    <ChangeTitleContainer
      onChangeItemName={onChangeItemName}
      closeMenuItem={handleClose}
      item={item}
    />
  );


  const renderAddTagPopUp = () => (
    <AddTagContainer
      item={item}
      userTagData={userTagData}
      selectedTags={selectedTags}
      onTagSelected={onTagSelected}
    />
  );

  const renderRemoveItemContainer = () => (
    <RemoveItemContainer
      item={item}
      onRemoveItem={onRemoveItem}
      closeMenuItem={handeleClose}
    />
  );

  const renderDefaultPopup = () => (
    <div><p>Standard menu post</p></div>
  );


  const menuItemPopUpSwitcher = (name) => {
    switch (name) {
      case ADDTAG:
        return renderAddTagPopUp();
      case CHANGETITLE:
        return renderChangeTitlePopUp();
      case REMOVEITEM:
        return renderRemoveItemContainer();
      default:
        return renderDefaultPopup();
    }
  };

  const handleMenuItemClick = (item, event) => {
    setAnchorEl(event.currentTarget);
    setSubMenuPopUpName(item.title);
    setAnchorEl(event.currentTarget);
    menuItemPopUpSwitcher(item);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <Fragment>
      <MoreButton
        data={data}
        handleMenuItemClick={handleMenuItemClick}
      />
      <Menu
        open={Boolean(anchorEl)}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'right',
        }}
      >

        {menuItemPopUpSwitcher(subMenuPopUpName)}

      </Menu>
    </Fragment>
  );
};custom 

【问题讨论】:

  • 如果您可以提供CodeSandbox 重现问题,那么提供帮助会更容易/更快。
  • 感谢 @RyanCogswell 我会检查 CodeSandbox,看起来它是测试事物的好方法。
  • @PatrikRikama-Hinnenberg 你解决了吗?我对 MUI 4.8.0 版有同样的问题
  • 是的,让我尝试提供示例@radzik。
  • 那里,希望示例答案能解释它@radzik。

标签: javascript reactjs material-ui


【解决方案1】:

能够通过为父锚添加另一个状态来解决问题。所以父菜单有自己的锚点,子菜单弹出自己的锚点,然后 handleClose() 禁用它们。请参阅示例和标有 //THIS IS NEW:

的 5 行
const MoreMenu = ({
  userTagData,
  onChangeItemName,
  selectedTags,
  onTagSelected,
  onRemoveItem,
  data,
  item,
}) => {
  const [parentAnchorEl, setParentAnchorEl] = useState(null); // THIS IS NEW
  const [anchorEl, setAnchorEl] = useState(null);
  const [subMenuPopUpName, setSubMenuPopUpName] = useState('');

  const handleMoreButtonClick = (event) => { // THIS IS NEW
    setParentAnchorEl(event.currentTarget);
  };

  const renderChangeTitlePopUp = () => (
    <ChangeTitleContainer
      onChangeItemName={onChangeItemName}
      closeMenuItem={handleClose}
      item={item}
    />
  );


  const renderAddTagPopUp = () => (
    <AddTagContainer
      item={item}
      userTagData={userTagData}
      selectedTags={selectedTags}
      onTagSelected={onTagSelected}
    />
  );

  const renderRemoveItemContainer = () => (
    <RemoveItemContainer
      item={item}
      onRemoveItem={onRemoveItem}
      closeMenuItem={handeleClose}
    />
  );

  const renderDefaultPopup = () => (
    <div><p>Standard menu post</p></div>
  );


  const menuItemPopUpSwitcher = (name) => {
    switch (name) {
      case ADDTAG:
        return renderAddTagPopUp();
      case CHANGETITLE:
        return renderChangeTitlePopUp();
      case REMOVEITEM:
        return renderRemoveItemContainer();
      default:
        return renderDefaultPopup();
    }
  };

  const handleMenuItemClick = (item, event) => {
    setAnchorEl(event.currentTarget);
    setSubMenuPopUpName(item.title);
    setAnchorEl(event.currentTarget);
    menuItemPopUpSwitcher(item);
  };

  const handleClose = () => {
    setAnchorEl(null);
    setParentAnchorEl(null); //THIS IS NEW
  };

  return (
    <Fragment>
      <MoreButton
        anchorEl={parentAnchorEl} //THIS IS NEW
        data={data}
        handleMenuItemClick={handleMenuItemClick}
        handleClick={handleMoreButtonClick}    //THIS IS NEW
      />
      <Menu
        open={Boolean(anchorEl)}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: 'top',
          horizontal: 'left',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'right',
        }}
      >

        {menuItemPopUpSwitcher(subMenuPopUpName)}

      </Menu>
    </Fragment>
  );
};custom 

【讨论】:

  • 同样的问题,但是你如何实现 ?因为你传递了handleClick 和handleMenuItemClick 我们不知道你是做什么用的?因为他们得到相同的事件,为什么他们会因为有两个而采取不同的行动?
  • const MoreButton = ({ data, handleMenuItemClick, anchorEl, handleClick, handleClose, }) =&gt; ( &lt;div&gt; &lt;MoreIconMUI onClick={handleClick} /&gt; &lt;Menu id="menu-appbar" anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose} &gt; {data.map(item =&gt; ( &lt;MenuItem key={item.title} onClick={event =&gt; handleMenuItemClick(item, event)} &gt; {item.title} &lt;/MenuItem&gt; ))} &lt;/Menu&gt; &lt;/div&gt; );
  • 抱歉回复晚了@UrosRandelovic 有两个状态和两个不同的锚点。
猜你喜欢
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 2013-11-30
  • 1970-01-01
相关资源
最近更新 更多