用法
了解使用 MUI System 及其工具的基础知识。
为什么使用 MUI System?
MUI System 的 sx
属性让您避免编写不必要的 styled-component 代码,而是直接在组件本身内定义样式。这对于具有自定义设计的一次性组件尤其有用。
以下代码示例说明了 styled-components 和 sx
之间的区别
- 使用 styled-components API
const StatWrapper = styled('div')(
({ theme }) => `
background-color: ${theme.palette.background.paper};
box-shadow: ${theme.shadows[1]};
border-radius: ${theme.shape.borderRadius}px;
padding: ${theme.spacing(2)};
min-width: 300px;
`,
);
const StatHeader = styled('div')(
({ theme }) => `
color: ${theme.palette.text.secondary};
`,
);
const StyledTrend = styled(TrendingUpIcon)(
({ theme }) => `
color: ${theme.palette.success.dark};
font-size: 16px;
vertical-alignment: sub;
`,
);
const StatValue = styled('div')(
({ theme }) => `
color: ${theme.palette.text.primary};
font-size: 34px;
font-weight: ${theme.typography.fontWeightMedium};
`,
);
const StatDiff = styled('div')(
({ theme }) => `
color: ${theme.palette.success.dark};
display: inline;
font-weight: ${theme.typography.fontWeightMedium};
margin-left: ${theme.spacing(0.5)};
margin-right: ${theme.spacing(0.5)};
`,
);
const StatPrevious = styled('div')(
({ theme }) => `
color: ${theme.palette.text.secondary};
display: inline;
font-size: 12px;
`,
);
return (
<StatWrapper>
<StatHeader>Sessions</StatHeader>
<StatValue>98.3 K</StatValue>
<StyledTrend />
<StatDiff>18.77%</StatDiff>
<StatPrevious>vs last week</StatPrevious>
</StatWrapper>
);
- 使用 MUI System
<Box
sx={{
bgcolor: 'background.paper',
boxShadow: 1,
borderRadius: 1,
p: 2,
minWidth: 300,
}}
>
<Box sx={{ color: 'text.secondary' }}>Sessions</Box>
<Box sx={{ color: 'text.primary', fontSize: 34, fontWeight: 'medium' }}>
98.3 K
</Box>
<Box
component={TrendingUpIcon}
sx={{ color: 'success.dark', fontSize: 16, verticalAlign: 'sub' }}
/>
<Box
sx={{ color: 'success.dark', display: 'inline', fontWeight: 'medium', mx: 0.5 }}
>
18.77%
</Box>
<Box sx={{ color: 'text.secondary', display: 'inline', fontSize: 12 }}>
vs. last week
</Box>
</Box>
sx 属性
MUI System 的核心实用程序是 sx
属性,它为您提供了一种快速有效的方法,将正确的设计令牌直接应用于 React 元素。
此属性提供 CSS 的超集(即它包含所有 CSS 属性和选择器以及自定义属性和选择器),根据所使用的 CSS 属性,直接从主题映射值。它还通过参考主题中定义的断点,简化了定义响应式值的过程。
访问 sx
属性页面 以了解完整详情。
响应式演示
以下演示展示了如何使用 sx
属性应用自定义样式,并仅使用 Box
包装器创建复杂的 UI 组件。调整窗口大小以查看响应式断点
何时使用 MUI System
sx
属性最适合将一次性样式应用于自定义组件。
这与 styled-components API 形成对比,后者非常适合构建需要支持各种上下文的组件。这些组件在应用程序的许多不同部分中使用,并支持不同的 props 组合。
性能权衡
MUI System 依赖 CSS-in-JS。它可以与 Emotion 和 styled-components 一起使用。
优点
- 📚
sx
属性使用 CSS 的超集,因此如果您已经了解 CSS,那么语法将立即让您感到熟悉。它还提供(可选的)速记定义,如果您花一些时间预先学习它们,可以节省您的时间。这些内容记录在左侧主导航的样式工具部分中。 - 📦 系统自动清除,因此只有页面上使用的 CSS 会发送到客户端。初始捆绑包大小成本是固定的——当您添加更多 CSS 属性时,它不会变得更大。您需要支付 @emotion/react 和 @mui/system 的成本。总大小约为 15 kB gzip 压缩后的大小。但是,如果您已经在使用像 Material UI 这样的 MUI Core 组件库,则不会产生额外的开销。
缺点
运行时性能会受到影响。
基准测试用例 | 代码片段 | 时间归一化 |
---|---|---|
a. 渲染 1,000 个原始元素 | <div className="…"> |
100 毫秒 |
b. 渲染 1,000 个组件 | <Div> |
112 毫秒 |
c. 渲染 1,000 个 styled components | <StyledDiv> |
181 毫秒 |
d. 渲染 1,000 个 Box | <Box sx={…}> |
296 毫秒 |
访问 benchmark 文件夹 以重现上述指标。
我们认为对于大多数用例来说,它已经足够快了,但是当性能变得至关重要时,有一些简单的解决方法。例如,在渲染包含许多项的列表时,您可以使用 CSS 子选择器来获得单个“样式注入”点(包装器使用 d.,每个项使用 a.)。
API 权衡
MUI System 统一的 sx
属性有助于保持 CSS 工具和组件业务逻辑之间的关注点分离。
例如,按钮上的 color
prop 会影响多个状态(悬停、焦点等),并且与 CSS color
属性不同。
出于这个原因,只有 Box
、Stack
、Typography
和 Grid
组件接受 MUI System 属性作为 props。这些组件旨在解决 CSS 问题——它们是 CSS 组件实用程序。
在哪里使用 MUI System
sx
属性可以在四个不同的位置使用
核心组件
所有 Material UI 和 Joy UI 组件都支持 sx
属性。
Box
Box
是一个轻量级组件,它提供对 sx
属性的访问,可以用作实用程序组件,也可以用作其他组件的包装器。默认情况下,它渲染一个 <div>
元素。
自定义组件
除了 MUI System 组件,您还可以通过使用来自 @mui/material/styles
的 styled
实用程序,将 sx
属性添加到您的自定义组件中。
import { styled } from '@mui/material/styles';
const Div = styled('div')``;
任何带有 babel 插件的元素
访问 GitHub 上的未解决问题 以了解更多信息。
如何使用 MUI System
主题中的设计令牌
访问 System 属性页面 以了解不同的 CSS(和自定义)属性如何映射到主题键。
简写
许多 CSS 属性都有可用的简写。这些内容记录在它们各自的样式工具页面上。这是一个例子:
<Box
sx={{ boxShadow: 1, // theme.shadows[1]
color: 'primary.main', // theme.palette.primary.main
m: 1, // margin: theme.spacing(1)
p: {
xs: 1, // [theme.breakpoints.up('xs')]: { padding: theme.spacing(1) }
},
zIndex: 'tooltip', // theme.zIndex.tooltip
}}
>
这些简写是可选的——它们非常适合节省时间,但不是必须使用的
CSS 超集
sx
属性支持 CSS 语法,包括子选择器和伪选择器、媒体查询、原始 CSS 值等等。以下是如何实现这些 CSS 功能的一些示例
使用伪选择器
<Box sx={{ // some styles ":hover": { boxShadow: 6, }, }} >
使用媒体查询
<Box sx={{ // some styles '@media print': { width: 300, }, }} >
使用嵌套选择器
<Box sx={{ // some styles '& .ChildSelector': { bgcolor: 'primary.main', }, }} >
响应式值
sx
属性简化了定义和实现响应式断点的过程。您可以通过两种不同的方式定义一组断点:作为对象或作为数组。
作为对象的断点
断点的第一个选项是将它们定义为对象,使用断点值作为键。请注意,给定断点的每个属性也适用于集合中所有更大的断点。例如,width: { lg: 100 }
等同于 theme.breakpoints.up('lg')
。
以下演示展示了如何使用对象语法定义一组断点
简写语法是 @{断点}/{容器}
- 断点:
px
单位的数字或断点键(例如默认断点的sm
、md
、lg
、xl
)或有效的 CSS 值(例如40em
)。 - 容器(可选):包含上下文的名称。
作为数组的断点
第二个选项是将您的断点定义为数组,从小到大排列。这是它的样子
您可以使用 null
值跳过断点
<Box sx={{ width: [null, null, 300] }}>This box has a responsive width.</Box>
自定义断点
您还可以指定自己的自定义断点,并在定义断点对象时将它们用作键。这是一个如何做到这一点的示例
import * as React from 'react';
import Box from '@mui/material/Box';
import { createTheme, ThemeProvider } from '@mui/material/styles';
const theme = createTheme({
breakpoints: {
values: {
mobile: 0,
tablet: 640,
laptop: 1024,
desktop: 1280,
},
},
});
export default function CustomBreakpoints() {
return (
<ThemeProvider theme={theme}>
<Box
sx={{
width: {
mobile: 100,
laptop: 300,
},
}}
>
This box has a responsive width
</Box>
</ThemeProvider>
);
}
如果您正在使用 TypeScript,您还需要使用 模块增强,以便主题接受上述值。
declare module '@mui/material/styles' {
interface BreakpointOverrides {
xs: false; // removes the `xs` breakpoint
sm: false;
md: false;
lg: false;
xl: false;
tablet: true; // adds the `tablet` breakpoint
laptop: true;
desktop: true;
}
}
主题 getter
如果您希望将主题用于 MUI System 本身不支持的 CSS 属性,那么您可以将一个函数用作值,您可以在其中访问主题对象。以下演示展示了它是如何工作的