如何在Material UI中使用sx属性实现选中组件的专属样式?
问题描述
已通过useState实现ListItem点击选中状态切换,希望通过sx属性而非styled component实现选中时的自定义样式:选中时ListItem背景变为浅蓝色,ListItemText文字变为蓝色。但尝试多种类选择方式均未生效,相关代码见下文。
解决方案
问题出在选择器使用错误以及样式层级理解偏差,以下是修正后的实现方式:
关键修改点
ListItem的选中状态样式需要直接作用于内部的ListItemButton,因为它是实际的可点击容器- 无需给
ListItemText单独设置selected属性,通过父元素的选中状态即可控制文字颜色 - 使用正确的MUI类选择器语法,比如
&.Mui-selected来匹配选中的ListItem,避免冗余的嵌套选择器
修正后的代码
import { useState, useContext } from 'react' import { Box, Drawer, Avatar, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; import Typography from '@mui/material/Typography'; import HomeOutlinedIcon from "@mui/icons-material/HomeOutlined" import PeopleOutlinedIcon from "@mui/icons-material/PeopleOutlined" import PersonOutlinedIcon from "@mui/icons-material/PersonOutlined" import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined'; import HelpOutlinedIcon from "@mui/icons-material/HelpOutlined" import PieChartOutlineOutlinedIcon from "@mui/icons-material/PieChartOutlineOutlined" import TimelineOutlinedIcon from "@mui/icons-material/TimelineOutlined" import FolderSharedOutlinedIcon from '@mui/icons-material/FolderSharedOutlined'; import { Link as RouterLink } from 'react-router-dom' import { useTheme } from '@mui/material' import { ColorModeContext, tokens } from "./../theme" import Logo from "./../assets/code2.jpg" const SideBar = () => { const theme = useTheme(); const colorMode = useContext(ColorModeContext); const colors = tokens(theme.palette.mode); const [selected, setSelected] = useState("Dashboard") const handleListItemClick = (text) => { setSelected(text) } const Item = ({ icon, text, to, selected }) => { return ( <ListItem key={text} selected={selected === text} disablePadding onClick={() => handleListItemClick(text)} sx={{ // 选中状态下的样式 '&.Mui-selected': { '& .MuiListItemButton-root': { backgroundColor: 'lightblue', }, '& .MuiListItemText-primary': { color: 'blue', } }, // 选中时的hover状态 '&.Mui-selected:hover': { '& .MuiListItemButton-root': { backgroundColor: 'aliceblue', } } }} > <ListItemButton component={RouterLink} to={to}> <ListItemIcon> {icon} </ListItemIcon> <ListItemText primary={text} /> </ListItemButton> </ListItem> ) } return ( <Drawer sx={{ width: 240, flexShrink: 0, '& .MuiDrawer-paper': { p: 2, width: 240, boxSizing: 'border-box', backgroundColor: `${colors.primary[500]}`, } }} variant="permanent" anchor="left"> <Box textAlign="center" m="0 0 15px 0"> <Typography variant="h3" color={colors.grey[100]} fontWeight="bold" sx={{ m: "10px 0 0 0" }}> ADMINIS</Typography> </Box> <Box mb="10px"> <Box display="flex" justifyContent="center" alignItems="center"> <Avatar alt="logo" src={Logo} sx={{ width: 100, height: 100, cursor: "pointer"}} /> </Box> </Box> <Box textAlign="center"> <Typography variant="h2" color={colors.grey[100]} fontWeight="bold" sx={{ m: "10px 0 0 0" }}> Huvon Goodridge</Typography> <Typography variant="h5" color={colors.greenAccent[500]}>VP Fancy Admin</Typography> </Box> <List> <Item selected={selected} icon={<HomeOutlinedIcon />} text={"Dashboard"} to={'dashboard'} /> </List> <Typography variant="h6" color={colors.grey[300]} sx={{ m: "15px 0px 0px 5px" }}> Data </Typography> <List> <Item selected={selected} icon={<PeopleOutlinedIcon />} text={"Team"} to={'team'} /> <Item selected={selected} icon={<FolderSharedOutlinedIcon />} text={"Projects"} to={"projects"} /> </List> <Typography variant="h6" color={colors.grey[300]} sx={{ m: "15px 0px 0px 5px" }}> Pages </Typography> <List> <Item selected={selected} icon={<PersonOutlinedIcon />} text={"Profile"} to={'profile'} /> <Item selected={selected} icon={<CalendarTodayOutlinedIcon />} text={"Calendar"} to={'calendar'} /> <Item selected={selected} icon={<HelpOutlinedIcon />} text={"FAQ"} to={'faq'} /> </List> <Typography variant="h6" color={colors.grey[300]} sx={{ m: "15px 0px 0px 5px" }}> Charts </Typography> <List> <Item selected={selected} icon={<PieChartOutlineOutlinedIcon />} text={"Pie Chart"} to={'piechart'} /> <Item selected={selected} icon={<TimelineOutlinedIcon />} text={"Timeline"} to={'timeline'} /> </List> </Drawer> ) } export default SideBar;
说明
- 直接在
ListItem的sx属性中使用&.Mui-selected匹配选中状态,然后通过后代选择器控制ListItemButton的背景色和ListItemText的文字颜色 - 移除了
ListItemText上多余的selected属性和无效的样式定义,简化了代码结构 - 保持了原有的状态管理逻辑,仅调整了样式部分的实现
内容的提问来源于stack exchange,提问作者LordEscanor
相关产品推荐
相关产品推荐

