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

如何在Material UI styled中跨不同元素复用相同样式?

MUI Styled图标组件样式复用方案

问题场景

开发过程中使用两个Material UI图标,二者需要应用完全相同的样式,但编写mui-styled样式组件时存在重复代码,无法直接复用样式。
当前重复实现的代码如下:

import { styled } from '@mui/material/styles';
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';

const StyledExpandableKeyboardArrowDown = styled(KeyboardArrowDown)(({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  borderRadius: '50%',
  color: theme.palette.common.white,
  fontSize: '1rem'
}));

const StyledExpandableKeyboardArrowRight = styled(KeyboardArrowRight)(({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  borderRadius: '50%',
  color: theme.palette.common.white,
  fontSize: '1rem'
}));

上述代码中,为两个不同图标创建的styled组件样式完全一致,需要实现样式复用,无需分别维护两份相同的样式配置。

可行实现方案

方案1:抽离公共样式配置(推荐,改动最小)

直接把重复的样式逻辑抽离为独立的可复用函数,创建不同图标的styled组件时直接传入该公共样式函数即可,不会丢失主题访问、动态props响应的能力。
实现代码:

import { styled } from '@mui/material/styles';
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';

// 抽离公共样式逻辑,支持访问theme、组件props
const commonExpandIconStyle = ({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  borderRadius: '50%',
  color: theme.palette.common.white,
  fontSize: '1rem'
});

// 两个图标组件直接复用同一份样式配置
const StyledExpandableKeyboardArrowDown = styled(KeyboardArrowDown)(commonExpandIconStyle);
const StyledExpandableKeyboardArrowRight = styled(KeyboardArrowRight)(commonExpandIconStyle);

方案2:创建通用样式包装组件(适合多图标复用场景)

如果后续还有更多同样式的图标需要使用,可以创建一个通用的图标包装组件,通过component属性指定要渲染的图标类型,只需要编写一次styled样式即可。
实现代码:

import { styled } from '@mui/material/styles';
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';

// 通用图标样式组件,过滤掉自定义的component属性避免透传到DOM
const StyledExpandIcon = styled('span', {
  shouldForwardProp: (propName) => propName !== 'component'
})(({ theme }) => ({
  display: 'inline-flex',
  verticalAlign: 'middle',
  '& .MuiSvgIcon-root': {
    backgroundColor: theme.palette.primary.main,
    borderRadius: '50%',
    color: theme.palette.common.white,
    fontSize: '1rem'
  }
}));

// 使用方式:直接传入对应图标组件即可
// <StyledExpandIcon component={KeyboardArrowDown} />
// <StyledExpandIcon component={KeyboardArrowRight} />

方案3:复用sx公共配置(适合局部轻量使用)

如果不想额外创建多个styled组件,也可以把公共样式抽离为对象,在使用图标时通过MUI的sx属性传入即可,适合样式逻辑简单、使用频次不高的场景。

import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';

// 公共sx样式配置
const expandIconSx = (theme) => ({
  backgroundColor: theme.palette.primary.main,
  borderRadius: '50%',
  color: theme.palette.common.white,
  fontSize: '1rem'
});

// 使用时直接传入sx配置
// <KeyboardArrowDown sx={expandIconSx} />
// <KeyboardArrowRight sx={expandIconSx} />

注意:如果样式需要根据组件状态(比如激活、禁用)动态变化,抽离的公共样式函数/对象同样支持接收组件props,和直接写在styled内的逻辑完全一致,没有能力限制。

内容的提问来源于stack exchange,提问作者SDK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:21:37