【问题标题】:Using Grid List and Icon Button in Material UI as separate buttons with onClick action?将 Material UI 中的网格列表和图标按钮用作具有 onClick 操作的单独按钮?
【发布时间】:2020-10-13 21:38:31
【问题描述】:

我正在尝试使用 Material UI 框架中的这个网格列表:https://material-ui.com/components/grid-list/#grid-list-with-titlebars

我正在尝试将 onClick 操作添加到每个图块的 GridListTile 组件和 IconButton 组件。我已经能够这样做,但是当我单击 IconButton 时,这也注册为对 GridListTile 的单击。这是我当前代码的 sn-p:

<GridList cellHeight={200} className={classes.gridList} cols={Math.round(width/300)} spacing={6}>
    {tileData.map((tile) => (
      <GridListTile key={tile.img} onClick={() => {console1(tile.author)}}>
        <img src={tile.img} alt={tile.title}/>
        <GridListTileBar
          title={tile.title}
          subtitle={<span>by: {tile.author}</span>}
          actionIcon={
            <IconButton aria-label={`info about ${tile.title}`} className={classes.icon} onClick={() => {console2()}}>
              <InfoIcon />
            </IconButton>
          }
        />
      </GridListTile>
    ))}
  </GridList>

console1 和 console2 是我当前的函数,它们分别在单击 GridListTile 和 IconButton 时激活。本质上,当我单击 IconButton 时,console1 和 console2 都会激活,而只有 console2 应该激活。如果有人可以帮助我了解正在发生的事情并调整我的代码以解决此问题,我将不胜感激。谢谢。

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案1】:

    你需要设置你点击的元素的索引。 Codesandbox 与您上面列出的示例。

    更新的 Codesandbox: https://codesandbox.io/s/material-ui-grid-stacking-forked-2b1r4

    import React from "react";
    import { makeStyles } from "@material-ui/core/styles";
    import GridList from "@material-ui/core/GridList";
    import GridListTile from "@material-ui/core/GridListTile";
    import GridListTileBar from "@material-ui/core/GridListTileBar";
    import ListSubheader from "@material-ui/core/ListSubheader";
    import IconButton from "@material-ui/core/IconButton";
    import InfoIcon from "@material-ui/icons/Info";
    // import tileData from './tileData';
    
    const tileData = [
      {
        image: "https://via.placeholder.com/150",
        title: "Title 1",
        icon: "Title Icon 1"
      },
      {
        image: "https://via.placeholder.com/150",
        title: "Title 2",
        icon: "Title Icon 2"
      },
      {
        image: "https://via.placeholder.com/150",
        title: "Title 3",
        icon: "Title Icon 3"
      }
    ];
    
    const useStyles = makeStyles((theme) => ({
      root: {
        display: "flex",
        flexWrap: "wrap",
        justifyContent: "space-around",
        overflow: "hidden",
        backgroundColor: theme.palette.background.paper
      },
      gridList: {
        width: 500,
        height: 450
      },
      icon: {
        color: "rgba(255, 255, 255, 0.54)"
      }
    }));
    
    export default function GridComponent() {
      const classes = useStyles();
    
      const [title, setTitle] = React.useState("");
      const [selected, setSelected] = React.useState();
    
      function handleClick(index, title) {
        console.log("title", title);
        setSelected(index);
        setTitle(title);
      }
    
      function handleIconClick(index, icon) {
        console.log("icon", icon);
        setSelected(index);
        setTitle(icon);
      }
    
      return (
        <div className={classes.root}>
          <GridList cellHeight={180} className={classes.gridList}>
            <GridListTile key="Subheader" cols={2} style={{ height: "auto" }}>
              <ListSubheader component="div">{title}</ListSubheader>
            </GridListTile>
            {tileData.map((tile, index) => (
              <GridListTile
                className={index === selected ? "selected" : ""}
                key={`${index}${title.title}`}
              >
                <img
                  src={tile.image}
                  alt={tile.title}
                  onClick={() => handleClick(index, tile.title)}
                />
                <GridListTileBar
                  title={tile.title}
                  subtitle={<span>by: {tile.author}</span>}
                  actionIcon={
                    <IconButton
                      aria-label={`info about ${tile.title}`}
                      className={classes.icon}
                      onClick={() => handleIconClick(index, tile.icon)}
                    >
                      <InfoIcon />
                    </IconButton>
                  }
                />
              </GridListTile>
            ))}
          </GridList>
        </div>
      );
    }
    

    【讨论】:

    • 当用户点击图标按钮而不是网格图块时,这是否有单独的 onClick 函数?
    • 它包裹在容器中,所以只需将其拉出即可。更新了沙盒
    【解决方案2】:

    原因是事件冒泡。您可以了解更多关于事件冒泡的信息:https://www.tutorialspoint.com/what-is-event-bubbling-in-javascript

    当您单击 IconButton 时,单击事件会冒泡到 GridListTile。

    所以他们的console2和console1都被触发了。

    您需要使用 stopPropagation 来限制事件冒泡。

    这里是

    console1(e, author) {
     console.log(author);
    }
    
    console2(e) {
     e.stopPropagation();
     console.log('console2');
    }
    
    <GridList cellHeight={200} className={classes.gridList} cols={Math.round(width/300)} spacing={6}>
        {tileData.map((tile) => (
          <GridListTile key={tile.img} onClick={(e) => {console1(e, tile.author)}}>
            <img src={tile.img} alt={tile.title}/>
            <GridListTileBar
              title={tile.title}
              subtitle={<span>by: {tile.author}</span>}
              actionIcon={
                <IconButton aria-label={`info about ${tile.title}`} className={classes.icon} onClick={(e) => {console2(e)}}>
                  <InfoIcon />
                </IconButton>
              }
            />
          </GridListTile>
        ))}
      </GridList>
    

    现在

    如果您在 IconButton 外部单击 GridListTile,它将调用 console1

    如果你点击IconButton,它只会调用console2。

    【讨论】:

      猜你喜欢
      • 2019-06-13
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多