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

如何使用MUI为React可复用按钮设置不同样式

优化MUI可复用按钮组件的实现方案

我有一个可复用的React按钮组件,需要实现两种样式:

  • 绿色背景配白色文字
  • 白色背景配绿色文字及边框

目前是通过传递additionalStyles属性来实现第二种样式,想了解有没有更符合MUI设计思路的优化方案。

当前实现代码

页面使用示例

<MainButton title="Login" />
<MainButton
  title="Register"
  additionalStyles={{         // 额外添加的样式
    backgroundColor: "#e5f3fd",
    color: "#33b864",
    border: `1px solid ${theme.palette.secondary.main}`,
    "&:hover": {
      backgroundColor: "rgba(46, 171, 92, 0.1)",
    },
  }}
/>

MainButton组件代码

export const MainButton = ({ title, additionalStyles }: MainButtonProps) => {
  const theme = useTheme();

  return (
    <Button
      sx={{
        height: 40,
        bgcolor: theme.palette.secondary.main,
        color: "#ffffff",
        textTransform: "none",
        fontSize: 15,
        fontWeight: 600,
        borderRadius: 2,
        "&:hover": {
          bgcolor: "#2eab5c",
        },
        ...additionalStyles,
      }}
    >
      {title}
    </Button>
  );
};

更优的MUI实现方案

方案1:通过自定义variant属性控制样式

给组件新增variant属性,内部根据属性值切换预设样式,比传递零散样式更清晰易维护。

// 定义props类型
type MainButtonProps = {
  title: string;
  variant?: "primary" | "secondary"; // 自定义样式变体
};

export const MainButton = ({ title, variant = "primary" }: MainButtonProps) => {
  const theme = useTheme();

  // 提取公共基础样式
  const baseStyles = {
    height: 40,
    textTransform: "none",
    fontSize: 15,
    fontWeight: 600,
    borderRadius: 2,
  };

  // 根据变体匹配对应样式
  const variantStyles = variant === "primary" 
    ? {
        bgcolor: theme.palette.secondary.main,
        color: "#ffffff",
        "&:hover": { bgcolor: "#2eab5c" },
      }
    : {
        bgcolor: "#e5f3fd",
        color: "#33b864",
        border: `1px solid ${theme.palette.secondary.main}`,
        "&:hover": { bgcolor: "rgba(46, 171, 92, 0.1)" },
      };

  return <Button sx={{ ...baseStyles, ...variantStyles }}>{title}</Button>;
};

使用时直接指定变体即可:

<MainButton title="Login" /> {/* 默认primary样式 */}
<MainButton title="Register" variant="secondary" /> {/* 第二种样式 */}

方案2:用MUI styled API封装预定义组件

如果后续需要扩展更多样式,用styled把样式和组件绑定,逻辑更独立:

import { Button, styled } from "@mui/material";

// 基础按钮公共样式
const BaseButton = styled(Button)(({ theme }) => ({
  height: 40,
  textTransform: "none",
  fontSize: 15,
  fontWeight: 600,
  borderRadius: 2,
}));

// 主按钮样式(绿色背景白字)
const PrimaryMainButton = styled(BaseButton)(({ theme }) => ({
  bgcolor: theme.palette.secondary.main,
  color: "#ffffff",
  "&:hover": { bgcolor: "#2eab5c" },
}));

// 次按钮样式(白背景绿字边框)
const SecondaryMainButton = styled(BaseButton)(({ theme }) => ({
  bgcolor: "#e5f3fd",
  color: "#33b864",
  border: `1px solid ${theme.palette.secondary.main}`,
  "&:hover": { bgcolor: "rgba(46, 171, 92, 0.1)" },
}));

// 统一导出组件
export const MainButton = ({ title, variant = "primary" }: MainButtonProps) => {
  return variant === "secondary" 
    ? <SecondaryMainButton>{title}</SecondaryMainButton>
    : <PrimaryMainButton>{title}</PrimaryMainButton>;
};

方案3:扩展MUI全局主题的按钮变体

如果按钮样式需要在全项目复用,可以直接扩展MUI主题,把自定义变体加入全局按钮配置:

// 主题配置文件中扩展
import { createTheme } from "@mui/material/styles";

const theme = createTheme({
  components: {
    MuiButton: {
      variants: [
        {
          props: { variant: "main-primary" },
          style: {
            height: 40,
            bgcolor: "#33b864",
            color: "#ffffff",
            textTransform: "none",
            fontSize: 15,
            fontWeight: 600,
            borderRadius: 2,
            "&:hover": { bgcolor: "#2eab5c" },
          },
        },
        {
          props: { variant: "main-secondary" },
          style: {
            height: 40,
            bgcolor: "#e5f3fd",
            color: "#33b864",
            border: "1px solid #33b864",
            textTransform: "none",
            fontSize: 15,
            fontWeight: 600,
            borderRadius: 2,
            "&:hover": { bgcolor: "rgba(46, 171, 92, 0.1)" },
          },
        },
      ],
    },
  },
});

// 组件中直接使用全局变体
export const MainButton = ({ title, variant = "main-primary" }: MainButtonProps) => {
  return <Button variant={variant}>{title}</Button>;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:03:31