You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:40:10