【问题标题】:Close Persistent MUI Drawer on clicking outside单击外部时关闭持久 MUI 抽屉
【发布时间】:2019-06-01 06:34:57
【问题描述】:

我正在尝试在 MUI React 中使用 Drawer component。我希望Drawer component 中的状态在关闭抽屉组件时不应该丢失,因此我在抽屉组件中传递variant="persistent"

现在,问题是Persistent Drawer 默认情况下不提供backdrop functionality,这与temporary 抽屉不同,因此我无法在外部点击时关闭它。 我也试过{{ModalProps={{ onBackdropClick: this.toggleDrawer }} }},但还是不行。

有什么解决方法吗?

MUI 版本:1.0.0

谢谢

CodeSandbox link

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案1】:

    您可以通过在 appFrame 中添加一个 div 来实现这一点,该 div 有一个 onClick 可以像这样关闭抽屉:

    <div className={classes.appFrame}>
    {this.state.open ? 
        <div style={{ position: "fixed", zIndex: 1, left: 0, right: 0, top: 0, bottom: 0 }} 
            onClick={() => this.handleDrawerClose()} /> 
        : null
    }
    // rest of your code
    

    【讨论】:

    • 谢谢,@milo,但我一直在寻找 Material-UI API 解决方案。虽然你的答案是正确的。
    • 我改用这个解决方案,它就像一个魅力,所有其他 Material-UI 道具和 ClickAwayListener 都无法工作或不适合。
    【解决方案2】:

    您可以为此使用ClickAwayListener 组件。
    https://material-ui.com/api/click-away-listener/

    import ClickAwayListener from '@material-ui/core/ClickAwayListener';
    
    const drawer = (
          <ClickAwayListener onClickAway={this.handleDrawerClose}>
            <Drawer
              variant="persistent"
              anchor={anchor}
              open={open}
              classes={{
                paper: classes.drawerPaper
              }}
            >
              <div className={classes.drawerHeader}>
                <IconButton onClick={this.handleDrawerClose}>
                  {theme.direction === "rtl" ? (
                    <ChevronRightIcon />
                  ) : (
                    <ChevronLeftIcon />
                  )}
                </IconButton>
              </div>
              <Divider />
              <List>a asdasd</List>
              <Divider />
              <List>asdasd</List>
            </Drawer>
          </ClickAwayListener>
        );
    

    https://codesandbox.io/s/072ny1rjw

    【讨论】:

    • 这有点奇怪。我试图做同样的事情并且不得不谷歌,因为它让我感到困惑。每次点击其他地方时都会调用onClickedAway,即使在抽屉未打开时(所以它仍然呈现,当未打开时?)无论如何。这会导致打开/关闭函数发生冲突的一些行为,当我单击打开按钮时,也会从 ClickAwayListener 调用关闭函数。
    • 这很好用,除非您触发抽屉的按钮不在ClickAwayListener 之外。在这种情况下,您需要向onClickAway 函数添加逻辑以检查是否刚刚单击了ShowDrawerButton,然后不触发ClickAwayListener 的操作。
    • 是的,例如,我们可以将 ClickAwayListener 组件放在 AppBar 周围。要显示抽屉,我们单击 AppBar 中的菜单图标。所以抽屉显示或隐藏都不会有问题。
    【解决方案3】:

    为了让搜索者登陆这个问题。如果您在使用ClickAwayListener 时遇到问题并且没有使用variant='persistent'。试试这个:为ModalPropsonBackdropClick提供一个切换功能

    <Drawer
      open={drawerIsOpen}
      ModalProps={{ onBackdropClick: this.toggleDrawer }}
    >
      <MenuItem>drawer item 1</MenuItem>
    </Drawer>
    

    2021 年 7 月更新:

    我最近将material-ui/core 更新为版本4.12.1,并注意到onBackdropClick 已被弃用。相反,他们添加了对这个功能的原生支持,onClose 函数将在抽屉外点击时自动调用,现在它给出了一个 reason 来说明它被调用的原因:

    签名: function(event: object, reason: string) =&gt; void

    event:回调的事件源。

    reason: 可以是:“escapeKeyDown”、“backdropClick”

    在此处查看示例:https://material-ui.com/api/modal/ 向下滚动到 onBackDropClicked - 它对抽屉的工作方式与对抽屉的工作方式相同

    改为这样做:

    <Drawer
      open={drawerIsOpen}
      onClose={{ (ev, reason) => this.setState({ drawerIsOpen: false }) }}
    >
      <MenuItem>drawer item 1</MenuItem>
    </Drawer>
    

    【讨论】:

    • 谢谢。 ClickAwayListener 对我也不起作用,因为它在我尝试打开抽屉的那一刻触发,因此阻止了切换打开。这解决了这个问题,我个人认为它比公认的答案更优雅
    • 这只是因为你忽略了删除背景的variant="persistent"约束......它写在问题中。
    • 使用 variant="temporary" 时,ClickAwayListener 对我不起作用。这个解决方案效果很好。
    【解决方案4】:

    我花了一些时间训练来解决这个问题,但我发现了一个非常有用的解决方案,就是将变体更改为 Temporary 并使用 de onEscapeKeyDown 和 onBackdropClick,如下所示:

      <Drawer
        variant="temporary"
        onEscapeKeyDown={handleDrawerClose}
        onBackdropClick={handleDrawerClose}
        open={open}
        ...rest of your code...
    

    【讨论】:

    • 轻松搞定。非常感谢这个超级有用的解决方案。
    【解决方案5】:

    我不确定它是否适用于 1.0.0 版本,但这种方法对我有用,注意到我正在使用“material-ui/core @4.10”中的抽屉

    <Drawer ... open={this.state.open} onClose={() => this.handleDrawerClose()}>
    ....
    </Drawer>
    

    【讨论】:

      【解决方案6】:

      最近发现了这个简洁的 useOnClickOutside 钩子 => CodeSandBox 并用它替换了所有我的。比向 dom 中添加元素更优雅,并且非常易于与 Mui 一起使用,因为您可以将 ref prop 传递给任何 Material-ui 组件。

      【讨论】:

      • 如果你总是显示按钮,你会如何处理它?就像您想在按下按钮时关闭模式一样,但如果您在外部单击?正在努力解决那个问题。
      【解决方案7】:

      MUI v5 中的工作解决方案:

      持久Drawer

      使用ClickAwayListener 了解用户何时在Drawer 之外单击。您还需要设置mouseEvent="onMouseDown",否则在用户单击打开按钮后会触发onClickAway 回调并使Drawer 在打开之前立即关闭。

      <ClickAwayListener
        mouseEvent="onMouseDown"
        touchEvent="onTouchStart"
        open={open}
        onClickAway={() => open && setOpen(false)}
      >
        <Drawer variant="persistent" {...props} />
      </ClickAwayListener>
      

      临时Drawer

      <Drawer
        variant="temporary"
        open={open}
        onClose={(_, reason) =>
          reason === 'backdropClick' && setOpen(false)
        }
      >
      

      现场演示

      【讨论】:

        【解决方案8】:

        您可以在抽屉的打开属性中使用useState并在onClose属性中设置为false:

        onClose={() =&gt; setOpen(false)}

        在本例中,useState 名称为 ** open ** 和 ** setOpen **

        【讨论】:

        • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 2019-06-01
        • 2020-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-13
        • 1970-01-01
        • 1970-01-01
        • 2014-04-02
        相关资源
        最近更新 更多