【问题标题】:Multiple hover popovers from an array using Material-UI opens only one popover使用 Material-UI 的数组中的多个悬停弹出框仅打开一个弹出框
【发布时间】:2018-10-23 21:10:48
【问题描述】:

我正在尝试在一个页面上使用多个弹出框,但唯一要打开的弹出框是数组中的最后一个,无论您将鼠标悬停在哪个触发元素上。 这是使用 Material-UI v1.0.0-beta.46。

class MultiplePopover extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      open: false,
      anchorEl: null,
    };
    this.handlePopoverOpen = this.handlePopoverOpen.bind(this);
    this.handlePopoverClose = this.handlePopoverClose.bind(this);
  }
  handlePopoverOpen(event) {
    this.setState({
      anchorEl: event.target,
    });
  }
  handlePopoverClose() {
    this.setState({
      anchorEl: null,
    });
  }

  render() {
    const { classes } = this.props;
    const { anchorEl } = this.state;
    const open = !!anchorEl;


    const multi = [
      {
        _id: 0,
        name: 'name1',
        hoverText: 'text1',
        linkUrl: '#',
      },
      {
        _id: 1,
        name: 'name2',
        hoverText: 'text2',
        linkUrl: '#',
      },
      {
        _id: 2,
        name: 'name3',
        hoverText: 'text3',
        linkUrl: '#',
      },
    ]

    return (
      <div className="wrapper">
        <ul>
          {multi.map(m => (
            <li
              key={m._id}
            >
              <Typography
                onMouseEnter={this.handlePopoverOpen}
                onMouseLeave={this.handlePopoverClose}
              >
                {m.name} 
              </Typography>
              <Popover
                className={classes.popover}
                classes={{
                  paper: classes.paper,
                }}
                open={open}
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: 'bottom',
                  horizontal: 'center',
                }}
                transformOrigin={{
                  vertical: 'bottom',
                  horizontal: 'center',
                }}
              >
                <Typography>
                  <a
                    href="{m.linkUrl}"
                    target=" /blank"
                  >
                    {m.hoverText}
                  </a>
                </Typography>
              </Popover>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

我已尝试按照这篇帖子 Popover doesn't work if you have many of them on one page. How to manage them? 的答案进行操作,但无法正常工作。

知道如何让每个弹出框分别打开吗?

你可以在这里看到一个活生生的例子:https://codesandbox.io/s/1r1zjmj163

【问题讨论】:

    标签: reactjs react-redux material-ui


    【解决方案1】:

    你做的有点不对。

    首先。 open 声明状态中仅存在一些元素,但它没有声明 打开了哪个。我已经为该州带来了新的openedPopoverId(默认为空)。因此,在这种情况下,您必须签入您的 Popover 组件

    open={this.state.openedPopoverId === m._id}
    

    第二。您必须在 mouseEnter 事件上传递此值,以便:

    <Typography
      onMouseEnter={this.handlePopoverOpen}
    

    变成

    onMouseEnter={(e) => this.handlePopoverOpen(e, m._id)}
    

    第三。更改事件处理程序:

      handlePopoverOpen(event, popoverId) {
        this.setState({
          openedPopoverId: popoverId,
          anchorEl: event.target,
        });
      }
      handlePopoverClose() {
        this.setState({
          openedPopoverId: null,
          anchorEl: null,
        });
      }
    

    最终代码(经过测试,可以使用):

    import React from 'react';
    import PropTypes from 'prop-types';
    import { withStyles } from 'material-ui/styles';
    import Typography from 'material-ui/Typography';
    import Popover from 'material-ui/Popover';
    
    const styles = ({
      paper: {
        padding: '20px',
        width: '14vw',
      },
      popover: {
        pointerEvents: 'none',
      },
    });
    
    class MultiplePopover extends React.Component {
      constructor(props, context) {
        super(props, context);
        this.state = {
          open: false,
          anchorEl: null,
        };
        this.handlePopoverOpen = this.handlePopoverOpen.bind(this);
        this.handlePopoverClose = this.handlePopoverClose.bind(this);
      }
      handlePopoverOpen(event, popoverId) {
        this.setState({
          openedPopoverId: popoverId,
          anchorEl: event.target,
        });
      }
      handlePopoverClose() {
        this.setState({
          openedPopoverId: null,
          anchorEl: null,
        });
      }
    
      render() {
        const { classes } = this.props;
        const { anchorEl, openedPopoverId } = this.state;
    
        const multi = [
          {
            _id: 0,
            name: 'name1',
            hoverText: 'text1',
            linkUrl: '#',
          },
          {
            _id: 1,
            name: 'name2',
            hoverText: 'text2',
            linkUrl: '#',
          },
          {
            _id: 2,
            name: 'name3',
            hoverText: 'text3',
            linkUrl: '#',
          },
        ]
    
      console.log(openedPopoverId)
    
        return (
          <div className="wrapper">
            <ul>
              {multi.map(m => (
                <li
                  key={m._id}
                >
                  <Typography
                    onMouseEnter={(e) => this.handlePopoverOpen(e, m._id)}
                    onMouseLeave={this.handlePopoverClose}
                  >
                    {m.name} 
                  </Typography>
                  <Popover
                    className={classes.popover}
                    classes={{
                      paper: classes.paper,
                    }}
                    open={openedPopoverId === m._id}
                    anchorEl={anchorEl}
                    anchorOrigin={{
                      vertical: 'bottom',
                      horizontal: 'center',
                    }}
                    transformOrigin={{
                      vertical: 'bottom',
                      horizontal: 'center',
                    }}
                  >
                    <Typography>
                      <a
                        href="{m.linkUrl}"
                        target=" /blank"
                      >
                        {m.hoverText}
                      </a>
                    </Typography>
                  </Popover>
                </li>
              ))}
            </ul>
          </div>
        );
      }
    }
    
    MultiplePopover.propTypes = {
      classes: PropTypes.object.isRequired,
    };
    
    export default withStyles(styles)(MultiplePopover);
    

    【讨论】:

    • 太好了,在找到您的答案之前,我已经为这个问题苦苦挣扎了一段时间。效果很好!
    【解决方案2】:

    @asiniy 为什么注释掉 css 'pointerEvents' 会导致弹出框代码中断? 如果弹出框内有链接,这将导致问题。 css应该控制事件吗?

      popover: {
        //pointerEvents: 'none',
      },
    

    【讨论】:

    • 这救了我。通过该指针设置,我无法在弹出框上使用可点击元素。
    猜你喜欢
    • 2020-01-10
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 2016-04-19
    • 2021-12-12
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    相关资源
    最近更新 更多