gin*_*93r 4 typescript reactjs material-ui
我已经搞乱了这一点,并且不断遇到类型错误,所以一定是我遗漏了一些东西。
我想要做的是创建自己的组件,然后能够覆盖主题的组件部分中的某些样式。根据我所读到的内容,我需要将组件添加到 Components 接口,这允许我将该自定义组件添加到 中的部分components,ThemeOptions但我找不到任何描述如何添加styleOverrides或自定义道具的内容,root例如bottom我可以将它们拉出来并将样式应用到组件。
// module aug
declare module '@mui/material/styles'{
interface Components {MyComponent?:type of MyComponent}
}
// my component
type MyComponentProps = {prop1:string, prop2:string, styleOverrides?:{bottom:CSSProperties}
const MyComponent = ({prop1:string, props2:string}:MyComponentprops) => { return <> ... </> }
// theme options
const options = {components:MyComponent:{styleOverrides:{bottom:{color:'red'}}}}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误type {styleOverrides?:bottom:{color:string} } is not comparable to {prop1:string, prop2:string, styleOverrides}:MyComponentProps. type {styleOverrides?:bottom:{color:string}} provides no match for the signature {prop1:string, prop2:string, styleOverrides}:MyComponentProps):Element
我尝试了几种不同的方法来格式化组件的 props,但 styleOverrides 总是返回空。
我在这里做错了什么?
在您的模块增强示例中,您有,但您需要定义主题interface Components {MyComponent?:type of MyComponent}中将出现的类型的完整结构。MyComponent这意味着您需要指定defaultProps密钥和styleOverrides密钥的完整结构(variants如果您想支持该概念,但我不关心示例中的变体)。您可以在此处查看MUI 如何为其每个组件定义这一点。
键defaultProps可以与组件的 props 具有相同的类型(MyComponentProps在我的示例中)。
关键styleOverrides是要复杂一些。您可以在此处查看MUI 如何为组件定义此类型,并且我的示例重新使用了 MUI 的OverridesStyleRules类型。该类型泛型的主要“输入”是允许的类键。我的示例在类型中定义了这一点MyComponentClassKey。为了对 MUI 方法进行建模,通常您将为最外面的组件定义一个“根”类键,然后为嵌套在其中的任何元素定义附加键(例如,在我的示例中为“底部”)。
下一步是利用组件中主题的defaultProps和。您可以在这里styleOverrides看到MUI 如何使用支持默认 props,我的示例使用相同的方法。为了支持样式覆盖,您可以使用 API传递第二个选项参数,该参数指示组件名称、插槽(即哪个 CSS 类键),以及确定样式覆盖的哪些部分适用于该插槽(并且它可能如果处理变体,请考虑道具/状态)。您可以在此处查看 MUI 中的示例。useThemePropsstyledoverridesResolver
下面是一个完整的工作示例:
import * as React from "react";
import {
createTheme,
ThemeProvider,
Theme,
styled,
useThemeProps
} from "@mui/material/styles";
import { OverridesStyleRules } from "@mui/material/styles/overrides";
interface MyComponentProps {
greetee?: string;
}
type MyComponentClassKey = "root" | "bottom";
const MyComponentRoot = styled("div", {
name: "MyComponent",
slot: "Root",
overridesResolver: (props, styles) => styles.root
})(({ theme }) => {
return {
padding: 8
};
});
const MyComponentBottom = styled("div", {
name: "MyComponent",
slot: "Bottom",
overridesResolver: (props, styles) => styles.bottom
})(({ theme }) => {
return {
borderBottom: "1px solid black"
};
});
const MyComponent = React.forwardRef(function MyComponent(
inProps: MyComponentProps,
ref
) {
const props = useThemeProps({ props: inProps, name: "MyComponent" });
const { greetee } = props;
return (
<MyComponentRoot>
Hello {greetee}
<MyComponentBottom />
</MyComponentRoot>
);
});
declare module "@mui/material/styles" {
interface Components {
MyComponent?: {
defaultProps?: MyComponentProps;
styleOverrides?: Partial<
OverridesStyleRules<MyComponentClassKey, "MyComponent", Theme>
>;
};
}
}
const theme = createTheme({
components: {
MyComponent: {
defaultProps: {
greetee: "World!"
},
styleOverrides: {
root: {
backgroundColor: "green",
padding: 16
},
bottom: {
borderColor: "purple"
}
}
}
}
});
export default function CustomStyles() {
return (
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
);
}
Run Code Online (Sandbox Code Playgroud)