如何在Material-UI中将锚点设置为弹出窗口

5
我有一个在Material-UI中的Popover,我想永久地将锚点设置为一个按钮,而不仅仅是在单击时使用event.currentTarget。我如何在typescript中实现这一点?
不幸的是,Material-UI中当前的示例使用event.currentTarget,并且使用引用不起作用。
import React,{useRef} from 'react';
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
import Popover from '@material-ui/core/Popover';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    typography: {
      padding: theme.spacing(2),
    },
  }),
);

export default function SimplePopover() {
  const classes = useStyles();

  const ref = useRef(null)


  return (
    <div>
      <Button ref={ref}  variant="contained" color="primary">
        Open Popover
      </Button>
      <Popover
        open
        anchorEl={ref}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'center',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'center',
        }}
      >
        <Typography className={classes.typography}>The content of the Popover.</Typography>
      </Popover>
    </div>
  );
}

这里有一个codesandbox。

2个回答

8
你可能错过了一些细节。我按照官方文档中的简单气泡示例进行了操作,仍然有效。
如果你想使用useRef,请确保在设置anchorRef时引用buttonRef.current
以下是代码沙盒的分支版本: Edit Popover Anchor

它可以与 event.currentTarget 一起使用。我的问题是如何在没有 event.currentTarget 的情况下永久将 anchorEl 设置为按钮。 - Jöcker
谢谢!你知道吗,为什么当我将open={open}更改为open时,它不再引用锚点了吗?https://codesandbox.io/s/popover-anchor-5xdon?file=/demo.tsx:935-946 - Jöcker
2
@Jöcker 是的,首先,当组件被挂载时,buttonRef.currentnull,因此在 buttonRef 引用到 <Button> 之前,您还需要将 prop anchorRef 直接设置为 null,否则会导致不必要的行为。为了避免这种情况,请使用 useEffect 监听 buttonRef 的变化。这是 forked codesandbox - hgb123
1
我建议将 useEffect 的注释突出显示 - 这为我省去了一些麻烦,但在评论区里几乎被我错过了。 - McAden

3

两件事情

  • 你需要存储打开弹出窗口的状态
  • 从外部打开它
  • 从内部关闭它

相关的JS

import React, { useRef, useState } from "react";
import { makeStyles, createStyles, Theme } from "@material-ui/core/styles";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    typography: {
      padding: theme.spacing(2)
    }
  })
);

export default function SimplePopover() {
  const classes = useStyles();

  const ref = useRef(null);

  const [popOverVisible, setPopOverVisible] = useState(false);
  const togglePopOver = () => {
    popOverVisible === false
      ? setPopOverVisible(true)
      : setPopOverVisible(false);
  };

  return (
    <div>
      <Button
        ref={ref}
        variant="contained"
        color="primary"
        onClick={togglePopOver}
      >
        Open Popover
      </Button>
      Status: {popOverVisible.toString()}
      <Popover
        open={popOverVisible}
        anchorEl={ref}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "center"
        }}
      >
        <Button
          ref={ref}
          variant="contained"
          color="primary"
          onClick={togglePopOver}
        >
          CLOSE Popover
        </Button>
        <Typography className={classes.typography}>
          The content of the Popover.
        </Typography>
      </Popover>
    </div>
  );
}

编辑:根据下面用户的评论:

      <Popover
    open={popOverVisible}
    anchorEl={ref}
    anchorReference="anchorPosition"
    anchorPosition={{ top: 50, left: 140 }}
    anchorOrigin={{
      vertical: "bottom",
      horizontal: "left"
    }}
    transformOrigin={{
      vertical: "top",
      horizontal: "left"
    }}
  >

分叉 这里


Popover 应该在按钮的上下角。使用 ref,它会出现在屏幕中央... - Jöcker
1
@Jöcker,我添加了anchorReference="anchorPosition"anchorPosition={{ top: 50, left: 140 }}来满足你的需求。 - Akber Iqbal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接