点击Material-UI ImageListItemBar按钮后,多图片场景下Dialog的控制问题
解决MUI多张图片点击弹窗展示的问题
问题场景
点击ImageListItemBar中的IconButton时,需要在屏幕前端展示对应的图片,但因为有多张图片,处理Dialog的open和onClose属性时遇到了困难。原代码如下:
import * as React from 'react'; import Box from '@mui/material/Box'; import ImageList from '@mui/material/ImageList'; import ImageListItem from '@mui/material/ImageListItem'; import ImageListItemBar from '@mui/material/ImageListItemBar'; import IconButton from '@mui/material/IconButton'; import VisibilityIcon from '@mui/icons-material/Visibility'; import Dialog from '@mui/material/Dialog'; export default function MasonryImageList({ data }) { const itemData = data.map((image) => { return { img: image.url, title: image.titre } }) return ( <Box id='Mansonry'> <ImageList variant="masonry" cols={3} gap={8}> {itemData.map((item, index) => ( <> <ImageListItem key={item.img}> <img srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`} src={`${item.img}?w=248&fit=crop&auto=format`} alt={item.title} loading="lazy" /> <ImageListItemBar title={item.title} actionIcon={ <IconButton sx={{ color: 'rgba(255, 255, 255, 0.54)' }} aria-label={`Agrandir ${item.title}`} onClick={() => { //When clicked, display the image on the MUI Dialog }} > <VisibilityIcon /> </IconButton> } /> </ImageListItem> <Dialog onClose={handleClose} open={open}> //How should i handle the opening and closing of each Dialog for each Image ? <img src={`${item.img}`} alt={item.title} loading="lazy" /> </Dialog> </> ))} </ImageList> </Box> ); }
解决方案
不用给每张图片都渲染一个Dialog,只需要维护一个全局的弹窗状态,记录当前选中的图片即可:
- 新增两个状态变量:
open控制弹窗显示/隐藏,selectedImage存储当前要展示的图片信息 - 点击图标按钮时,将当前图片信息存入
selectedImage,并打开弹窗 - 弹窗关闭时,重置状态
- 将
Dialog移到循环外部,仅渲染一个,根据selectedImage展示对应图片
修改后的完整代码
import * as React from 'react'; import Box from '@mui/material/Box'; import ImageList from '@mui/material/ImageList'; import ImageListItem from '@mui/material/ImageListItem'; import ImageListItemBar from '@mui/material/ImageListItemBar'; import IconButton from '@mui/material/IconButton'; import VisibilityIcon from '@mui/icons-material/Visibility'; import Dialog from '@mui/material/Dialog'; export default function MasonryImageList({ data }) { // 新增状态:控制弹窗显示、存储选中的图片 const [open, setOpen] = React.useState(false); const [selectedImage, setSelectedImage] = React.useState(null); const itemData = data.map((image) => { return { img: image.url, title: image.titre } }); // 弹窗关闭处理函数 const handleClose = () => { setOpen(false); setSelectedImage(null); }; return ( <Box id='Mansonry'> <ImageList variant="masonry" cols={3} gap={8}> {itemData.map((item) => ( <ImageListItem key={item.img}> <img srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`} src={`${item.img}?w=248&fit=crop&auto=format`} alt={item.title} loading="lazy" /> <ImageListItemBar title={item.title} actionIcon={ <IconButton sx={{ color: 'rgba(255, 255, 255, 0.54)' }} aria-label={`放大 ${item.title}`} onClick={() => { // 点击时设置选中图片并打开弹窗 setSelectedImage(item); setOpen(true); }} > <VisibilityIcon /> </IconButton> } /> </ImageListItem> ))} </ImageList> {/* 只渲染一个Dialog,根据选中的图片展示内容 */} <Dialog onClose={handleClose} open={open}> {selectedImage && ( <img src={selectedImage.img} alt={selectedImage.title} loading="lazy" style={{ maxWidth: '90vw', maxHeight: '90vh' }} /> )} </Dialog> </Box> ); }
说明
- 这种方式避免了循环渲染多个
Dialog组件,性能更优 - 通过
selectedImage精准控制弹窗内展示的图片内容 - 关闭弹窗时同时清空选中的图片状态,避免残留数据
内容的提问来源于stack exchange,提问作者dvdmnc
相关产品推荐
相关产品推荐

