- 组件定制
我在这个项目中使用了多种自定义 Material UI 组件的方法:
- 使用内联属性和样式:
import { Typography } from "@mui/material";
<Typography
fontSize={18}
fontWeight={600}
style={{ textDecoration: "line-through" }}
>
TEXT
</Typography>
- 使用提供对主题和断点的访问的sx属性以及一些简写属性,例如and而不是and :
p``m``padding``margin
import { Typography, SxProps, Theme } from "@mui/material";
const MyStyles: SxProps<Theme> = (theme: Theme) => ({
mt: 7,
fontSize: {
xs: theme.typography.h4.fontSize,
md: theme.typography.h3.fontSize,
},
fontWeight: 600,
});
<Typography sx={MyStyles}>TEXT</Typography>
- 通过直接针对孩子的班级在父级上设置样式
Mui
:
(在这个例子中"&>p"
也可以工作,这个方法更适合其他组件Switch
和类".MuiSwitch-thumb"
)
import { Box, Typography } from "@mui/material";
<Box
sx={{ "&>.MuiTypography-root": { fontSize: 18, fontWeight: 600 } }}
>
<Typography>Text</Typography>
</Box>
- 在父项上设置样式并
inherit
在子项中使用
您可以将组件属性设置为具有“继承”的值,在这种情况下,它们会继承其父元素的样式。
import { Box, Typography } from "@mui/material";
<Box
sx={{ fontSize: 18, fontWeight: 600 }}
>
<Typography fontSize="inherit" fontWeight="inherit">
Text
</Typography>
</Box>
- 使用
styled()
实用程序:
import { Typography, TypographyProps, styled() } from "@mui/material";
const CustomTypography = styled(Typography)<TypographyProps>(({ theme }) => ({
fontSize: 18,
fontWeight: 600,
[theme.breakpoints.up("xs")]: {
textAlign: "center",
},
[theme.breakpoints.up("md")]: {
textAlign: "left",
},
}));
- 使用包装器组件:
import { Typography, TypographyProps } from "@mui/material";
const CustomTypography = (props: TypographyProps) => (
<Typography
fontSize={18}
fontWeight="600"
sx={{ textAlign: { xs: "center", md: "left" } }}
{...props}
>
{props.children}
</Typography>
);
-
styled()
使用实用程序和包装器组件 的组合:
import { Link, LinkProps, styled() } from "@mui/material";
const CustomLink = (props: LinkProps) => {
const MyLink = styled(Link)<LinkProps>(({ theme }) => ({
color: "inherit",
transition: theme.transitions.create(["color"], {
duration: theme.transitions.duration.standard,
}),
"&:hover": {
color: theme.palette.strongCyan.main,
},
}));
return (
<MyLink {...props} underline="none" rel="noopener">
{props.children}
</MyLink>
);
};
- 主题
您可以通过更改/添加自定义颜色或palette
设置默认使用的自定义字体来自定义 Material UI 主题。然后通过将您的组件包装在 a 中<ThemeProvider>
,theme
子组件将可以使用:
import {
ThemeProvider,
createTheme,
PaletteColor,
SimplePaletteColorOptions,
} from "@mui/material/styles";
declare module "@mui/material/styles" {
interface Palette {
strongCyan: PaletteColor;
}
interface PaletteOptions {
strongCyan: SimplePaletteColorOptions;
}
}
const theme = createTheme({
palette: {
strongCyan: { main: "hsl(171, 66%, 44%)" },
},
typography: {
fontFamily: "'Bai Jamjuree', 'sans-serif';",
},
});
...
<ThemeProvider theme={theme}>
<ChildComponent />
</ThemeProvider>
- CSS 重置/规范化
某些元素默认应用边距和填充值,这可能会弄乱布局。Material UI 提供了一个方便的组件,称为<CssBaseline>
CSS Reset 并删除那些讨厌的默认样式:
import { CssBaseline } from "@mui/material";
...
<CssBaseline>
<YourOtherComponents />
</CssBaseline>
- 过渡
要向 Material UI 组件添加过渡效果,您可以使用theme.transitions.create()
将要应用过渡效果的属性作为第一个参数并将设置对象作为第二个参数的函数。您可以将持续时间设置为主题中定义的值,以便在以后阶段轻松调整/更改:
sx={(theme) => ({
transition: theme.transitions.create(
["color", "background-color"],
{
duration: theme.transitions.duration.standard,
}
),
})}
- 媒体查询
Material UI 提供了一个方便的useMediaQuery()
钩子,我们可以使用它来检测屏幕尺寸并执行诸如在特定屏幕尺寸上显示/隐藏组件之类的操作,或者在我的情况下,在较小的屏幕上禁用动画延迟。
你可以像这样使用它:
import { useMediaQuery, Theme } from "@mui/material";
...
const matches = useMediaQuery((theme: Theme) => theme.breakpoints.up("md"));
在这种情况下,matches
如果屏幕大于md
(中等)则为真,否则为假。然后你可以像使用任何其他boolean
变量一样使用它来为你的逻辑/渲染添加条件。
您还可以使用精确的像素值:useMediaQuery('(min-width: 900px)')
- 自定义另一个组件的子组件
Material UI 中的某些组件内部还有其他嵌套组件。例如,一个组件内部Dialog
有一个组件。Paper
为了自定义嵌套组件的属性,它公开了一个名为的属性,PaperProps
您可以使用它来执行此操作。您必须检查Material UI API才能了解每个组件的所有可用属性。
<Dialog
PaperProps={{
sx: {
borderRadius: '1rem'
},
}}
>
...
</Dialog>
- 转发ref给子组件
有些组件Tooltip
需要分配ref
给它们的子组件才能正常工作,这意味着如果您将自定义组件放入组件中Tooltip
,则必须React.forwardRef()
与自定义组件一起使用,以便它接受一个ref
. Link
这就是我在自定义组件中实现自定义的方式Tooltip
:
import React from "react";
import { Link, Tooltip, LinkProps, TooltipProps } from "@mui/material";
// custom Tooltip wrapper component
const MyTooltip = (props: TooltipProps) => (
<Tooltip
{...props}
arrow
placement="top"
TransitionComponent={Fade}
TransitionProps={{ timeout: 500 }}
>
{props.children}
</Tooltip>
);
// custom Link wrapper component
const MyLink = React.forwardRef<HTMLAnchorElement, LinkProps>(
(props, ref) => {
const linkStyles = (theme: Theme) => ({
transition: theme.transitions.create(["filter", "transform", "border"], {
duration: theme.transitions.duration.standard,
}),
"&:hover": {
filter: "brightness(150%)",
transform: "scale(1.2)",
},
});
return (
<Link {...props} target="_blank" rel="noopener" sx={linkStyles} ref={ref}>
{props.children}
</Link>
);
}
);
...
<MyTooltip title="React.js">
<MyLink href="https://react.dev" target="_blank">
React.js
</MyLink>
</MyTooltip>
而不是React.forwardRef<HTMLAnchorElement, LinkProps>(props, ref)
你可以使用React.forwardRef((props: LinkProps, ref: React.Ref<HTMLAnchorElement>)
- 修改/合并sx属性
有时您需要使用sx
已经定义的属性,但需要更改或删除其中的某些属性。有多种方法可以做到这一点:
sx1. 从prop 中移除属性
假设我们想从下面的 prop 中移除 backgroundColor sx
:
import { SxProps } from "@mui/material";
const myProp: SxProps = {
color: "red",
backgroundColor: "blue",
}
- 使用扩展运算符
const {backgroundColor, ...myNewProp} = myProp;
- 删除密钥
import { SystemCssProperties } from "@mui/system";
const myNewProp: SystemCssProperties = myProp;
delete myNewProp.backgroundColor;
- 通过合并重置密钥
您可以通过将您的道具与另一个道具backgroundColor
合并来重置该属性:合并将在下一节中解释。sx``sx``{backgroundColor: "transparent"}
sx2. 添加/修改道具 属性
- 添加/修改密钥
myProp.backgroundColor = "green";
myProp.mt = 2;
- 您还可以通过将您的样式与将添加/替换所需键的另一个样式合并来实现此目的。(接下来解释)
3.合并多个sx属性
- 使用
sx
数组
sx
prop 接受一个数组作为输入,它可以包含多个sx
将合并在一起的属性:
<ComponentName sx={[{color: "red"},{backgroundColor: "blue"}]} />
- 使用
Object.assign()
sx
属性是对象,因此您可以使用[Object.assign()
]将多个sx
属性合并在一起:
const myNewProp: SxProps = Object.assign(myProp, {
backgroundColor: "green",
});
- 使用该
merge-sx
包 您可以使用mergeSx()
该包提供的功能来合并多个sx
属性。
npm install merge-sx
import { mergeSx } from "merge-sx";
const mySxProp1: SxProps = { ... }
const mySxProp2: SxProps = { ... }
const mySxProp3: SxProps = mergeSx(mySxProp1, mySxProp2);
这个包的好处是它SxProps
也适用于函数式,我将在接下来解释。
4.处理功能sx属性
sx
属性也可以是将作为theme
输入并返回SxProps
对象的函数:
import { SxProps, Theme } from "@mui/material";
const myStyles: SxProps<Theme> = (theme: Theme) => ({
fontSize: {
xs: theme.typography.h4.fontSize,
md: theme.typography.h3.fontSize,
},
});
这样您就可以在道具中使用主题中的变量sx
。
但这意味着您不能Object.assign()
直接使用或修改键,因为您不再处理对象。
在这种情况下,最好的方法就是使用sx
数组方法。一定要将主题sx
也传递给功能属性。而且你还需要为你的sx
道具使用更具体的类型:
import { SxProps, Theme } from "@mui/material";
// wrong type ("This expression is not callable." error)
const myStyle1 : SxProps<Theme> = (theme: Theme) => ({ ...
// correct type
import { SystemStyleObject } from "@mui/system";
type SxPropsFunc<T extends object> = (_: T) => SystemStyleObject<T>;
const myStyle1 : SxPropsFunc<Theme> = (theme: Theme) => ({...
// wrong ("No overload matches this call." error)
<Component sx={[myStyle1, myStyle2]} />
// correct
<Component
sx={[
(theme:Theme) => myStyle1(theme),
(theme:Theme) => myStyle2(theme)
]}
/>
弄清楚上面的正确类型花了很多时间…文章来源:https://www.toymoban.com/news/detail-758763.html
总的来说,合并的时候,可以使用merge-sx
前面提到的包,省去一些麻烦。你也可以传递主题:文章来源地址https://www.toymoban.com/news/detail-758763.html
import { SxProps, Theme } from "@mui/material";
const myStyles: SxProps<Theme> = (theme: Theme) => {...
<MyComponent
sx={
mergeSx<Theme>(
(theme:Theme) => {
fontSize: theme.typography.h4.fontSize
},
myStyles
)
}
/>
到了这里,关于Material UI 自定义 (TypeScript)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!