如何使用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
相关产品推荐
相关产品推荐

