【问题标题】:Material UI ClickAwayListener close when clicking itselfMaterial UI ClickAwayListener 在单击自身时关闭
【发布时间】:2019-08-04 05:59:29
【问题描述】:

我在 Popper 中显示了以下显示侧边栏开关。因此,理想情况下,如果您单击其他位置(Popper 元素之外),Popper 应该会消失。如果您在 Popper 元素内单击,它不应该去任何地方。当我点击 Switch 或 Display Sidebar 文本时,那个 Popper 消失了。我用<div> 包裹了 Popper,它也没有帮助。

波普尔https://material-ui.com/api/popper/

切换https://material-ui.com/api/switch/

ClickAwayListener https://material-ui.com/utils/click-away-listener/

下面是波普尔代码

<ClickAwayListener onClickAway={this.handleClickAway}>
      <div>
        <Popper className={classes.popper} id={id} open={open} placement="bottom-end" anchorEl={anchorEl} transition>
          {({ TransitionProps }) => (
            <Fade {...TransitionProps} timeout={350}>
              <Paper className={classes.SliderBox}>
                <Switch
                  checked={this.state.checkedB}
                  onChange={this.handleChange('checkedB')}
                  value="checkedB"
                  color="primary"
                  onClick={handleDrawer}
                  className={classNames(classes.menuButton, sidebar && classes.hide)}
                />
                Display Sidebar
              </Paper>
            </Fade>
          )}
        </Popper>
        </div>
       </ClickAwayListener>

我在这里有示例(虽然我无法让它工作,但我不知道为什么它在点击时会出错) https://codesandbox.io/s/8pkm3x1902

【问题讨论】:

  • 如果您能提供一个重现此内容的CodeSandbox,将会很有帮助。我怀疑您应该将ClickAwayListener 直接放在Paper 周围(在Fade 内),但是没有简单的方法来尝试这个,我不确定这是正确的解决方案。
  • 好的,虽然我不知道为什么当我点击它时,clickawaylistener 会出错。 codesandbox.io/s/8pkm3x1902
  • 您没有定义 handleClickAway()。你能补充一下吗? @Extelliqent
  • 已修复,谢谢,在这里。 codesandbox.io/s/8pkm3x1902
  • 问题沙盒对我有用吗?

标签: reactjs material-ui


【解决方案1】:

默认情况下,Popper 利用 portal (https://github.com/mui-org/material-ui/blob/v4.11.0/packages/material-ui/src/Popper/Popper.js#L202) 将其内容呈现在 DOM 的单独部分中(作为 &lt;body&gt; 元素的直接子元素),而 Popper 元素所在的位置.这意味着您在空的&lt;div&gt; 周围有ClickAwayListener,因此在任意位置(包括在Popper 内容中)的点击将被视为在空的&lt;div&gt; 之外。

ClickAwayListener 直接移动到Fade 周围(而不是在Popper 周围)确保它围绕Popper 呈现的实际内容。

这是一个基于您的沙盒的工作示例:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Popper from "@material-ui/core/Popper";
import Fade from "@material-ui/core/Fade";
import Paper from "@material-ui/core/Paper";
import Switch from "@material-ui/core/Switch";
import Avatar from "@material-ui/core/Avatar";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";

class App extends Component {
  state = {
    anchorEl: null,
    open: false,
    checkedB: true
  };

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

  handleChange = (name) => (event) => {
    this.setState({
      [name]: event.target.checked
    });
  };

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

  render() {
    const { anchorEl, open } = this.state;
    const { handleDrawer } = this.props;
    const id = open ? "simple-popper" : null;
    return (
      <div className="App">
        asdsadsa
        <Avatar
          alt="Test"
          src="https://www.nretnil.com/avatar/LawrenceEzekielAmos.png"
          style={{ margin: "0 10px" }}
          onClick={this.handleClick}
        />
        <div>
          <Popper
            id={id}
            open={open}
            placement="bottom-end"
            anchorEl={anchorEl}
            transition
          >
            {({ TransitionProps }) => (
              <ClickAwayListener onClickAway={this.handleClickAway}>
                <Fade {...TransitionProps} timeout={350}>
                  <Paper //className={classes.SliderBox}
                  >
                    <Switch
                      checked={this.state.checkedB}
                      onChange={this.handleChange("checkedB")}
                      value="checkedB"
                      color="primary"
                      onClick={handleDrawer}
                    />
                    Display Sidebar
                  </Paper>
                </Fade>
              </ClickAwayListener>
            )}
          </Popper>
        </div>
      </div>
    );
  }
}

export default App;

ReactDOM.render(<App />, document.getElementById("root"));

在 v4 中,ClickAwayListener 支持识别元素在其 React 元素树中,即使它们在门户中呈现(最初的问题是针对 v3),但将 ClickAwayListener 放在Popper 而不是在外面,以避免 ClickAwayListener 在点击时触发以打开 Popper,这使得它看起来像 Popper 不工作,因为它会立即关闭(例如:https://codesandbox.io/s/popper-clickawaylistener-forked-x4j0l?file=/src/index.js)。

【讨论】:

  • 谢谢@Ryan,这行得通,但是,衰落运动不起作用。它用于在关闭期间打开平滑淡入和淡出...
  • 好的,我把它移到了 Fade 之外,它可以作为一个魅力,谢谢!
  • @Ryan Cogswell 非常感谢!那行得通!它是一个错误吗?也许我们应该在 MUI github 的存储库中打开一个问题?
  • @ManuelAbascal 不,这不是错误,只是使用不当。
  • @RyanCogswell 我不明白你所做的改变。似乎 OP 将 ClickAwayListener 作为一切的父级,但你把它变成了一个孩子。参考上的示例将其用作父级。你能详细说明你的解决方案吗?
【解决方案2】:

对我来说,只是制作popupOpen=false 并没有解决问题。所以,我也必须将 anchorElement 设置为 null,就像这样

const handleClickAway= ()=>{
popupOpen=false;   // Here you can also use state hook, but in my case, I'm using simpe boolean variable.
setAnchorEl(null);
}

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 2011-08-18
    • 2017-01-12
    • 1970-01-01
    • 2020-02-24
    • 2020-07-06
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多