Material-UI v5 使用 Emotion 作为默认样式引擎,并始终styled
在内部使用,以使想要使用 styled-components 而不是 Emotion 的人更容易不必将两者都包含在包中。
尽管styled
API 在很多用例中都可以正常工作,但对于这个特定用例来说似乎很笨拙。有两个主要选项可以提供更好的 DX。
一种选择是使用所有 Material-UI 组件上可用的新sx prop(并且Box 组件可用于包装非 MUI 组件以访问sx
功能)。下面是对演示此方法的 List 演示之一的修改(自定义ListItemButton
模拟您的角色ListItemLink
):
import * as React from "react";
import Box from "@material-ui/core/Box";
import List from "@material-ui/core/List";
import MuiListItemButton, {
ListItemButtonProps
} from "@material-ui/core/ListItemButton";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Divider from "@material-ui/core/Divider";
import InboxIcon from "@material-ui/icons/Inbox";
import DraftsIcon from "@material-ui/icons/Drafts";
const ListItemButton = ({
selected = false,
...other
}: ListItemButtonProps) => {
const match = selected;
return (
<MuiListItemButton
{...other}
sx={{ color: match ? "primary.main" : undefined }}
/>
);
};
export default function SelectedListItem() {
const [selectedIndex, setSelectedIndex] = React.useState(1);
const handleListItemClick = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
index: number
) => {
setSelectedIndex(index);
};
return (
<Box sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}>
<List component="nav" aria-label="main mailbox folders">
<ListItemButton
selected={selectedIndex === 0}
onClick={(event) => handleListItemClick(event, 0)}
>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItemButton>
<ListItemButton
selected={selectedIndex === 1}
onClick={(event) => handleListItemClick(event, 1)}
>
<ListItemIcon>
<DraftsIcon />
</ListItemIcon>
<ListItemText primary="Drafts" />
</ListItemButton>
</List>
<Divider />
<List component="nav" aria-label="secondary mailbox folder">
<ListItemButton
selected={selectedIndex === 2}
onClick={(event) => handleListItemClick(event, 2)}
>
<ListItemText primary="Trash" />
</ListItemButton>
<ListItemButton
selected={selectedIndex === 3}
onClick={(event) => handleListItemClick(event, 3)}
>
<ListItemText primary="Spam" />
</ListItemButton>
</List>
</Box>
);
}
这种方法的唯一缺点是它目前明显比 using慢styled
,但它仍然足够快,可以用于大多数用例。
另一种选择是通过其css prop直接使用 Emotion 。这允许类似的 DX(虽然使用主题不是很方便),但没有任何性能损失。
/** @jsxImportSource @emotion/react */
import * as React from "react";
import Box from "@material-ui/core/Box";
import List from "@material-ui/core/List";
import MuiListItemButton, {
ListItemButtonProps
} from "@material-ui/core/ListItemButton";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Divider from "@material-ui/core/Divider";
import InboxIcon from "@material-ui/icons/Inbox";
import DraftsIcon from "@material-ui/icons/Drafts";
import { css } from "@emotion/react";
import { useTheme } from "@material-ui/core/styles";
const ListItemButton = ({
selected = false,
...other
}: ListItemButtonProps) => {
const match = selected;
const theme = useTheme();
return (
<MuiListItemButton
{...other}
css={css({ color: match ? theme.palette.primary.main : undefined })}
/>
);
};
export default function SelectedListItem() {
const [selectedIndex, setSelectedIndex] = React.useState(1);
const handleListItemClick = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
index: number
) => {
setSelectedIndex(index);
};
return (
<Box sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}>
<List component="nav" aria-label="main mailbox folders">
<ListItemButton
selected={selectedIndex === 0}
onClick={(event) => handleListItemClick(event, 0)}
>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItemButton>
<ListItemButton
selected={selectedIndex === 1}
onClick={(event) => handleListItemClick(event, 1)}
>
<ListItemIcon>
<DraftsIcon />
</ListItemIcon>
<ListItemText primary="Drafts" />
</ListItemButton>
</List>
<Divider />
<List component="nav" aria-label="secondary mailbox folder">
<ListItemButton
selected={selectedIndex === 2}
onClick={(event) => handleListItemClick(event, 2)}
>
<ListItemText primary="Trash" />
</ListItemButton>
<ListItemButton
selected={selectedIndex === 3}
onClick={(event) => handleListItemClick(event, 3)}
>
<ListItemText primary="Spam" />
</ListItemButton>
</List>
</Box>
);
}
在我工作的应用程序中(我还没有开始迁移到 v5),我希望使用styled
和 Emotion 的css
功能/props的组合。我很犹豫要不要sx
大量使用这个props,直到它的性能有所提高(我认为这最终会发生)。尽管它在许多情况下“足够快”地执行,但当我有两个具有类似 DX 可用的选项并且一个的速度是另一个的两倍时,我发现很难选择较慢的一个。我选择sx
prop的主要情况是我想为不同的断点或类似区域设置不同的 CSS 属性的组件,在这些区域中,sx
prop 提供比其他选项更好的 DX。
相关回答: