v5 版本中的重大變更,第一部分:樣式與主題
這是一份關於 Material UI v5 中引入的重大變更以及如何從 v4 遷移的參考指南。本部分涵蓋樣式和主題的變更。
Material UI v5 遷移
- 開始使用
- 重大變更第一部分:樣式與主題 👈 您在這裡
- 重大變更第二部分:元件
- 從 JSS 遷移
- 疑難排解
重大變更,第一部分
Material UI v5 從 v4 引入了許多重大變更。許多這些變更可以使用 程式碼修改 (codemods) 自動解決,詳情請參閱主要遷移指南。
以下文件列出了 v5 中與樣式和主題相關的所有重大變更以及如何解決這些變更。
完成此處的步驟後,請繼續前往v5 版本中的重大變更,第二部分:元件,以繼續遷移流程。
將主題 styleOverrides 遷移至 Emotion
重構本機規則參考
儘管您在主題中定義的樣式覆寫可能部分有效,但在樣式化巢狀元素的方式上存在重要差異。
與 JSS 一起使用的 $
語法 (本機規則參考) 不適用於 Emotion。您需要將這些選取器替換為有效的類別選取器。
替換狀態類別名稱
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '&$focused': {
+ '&.Mui-focused': {
borderWidth: 1,
}
}
}
}
}
});
將巢狀類別選取器替換為全域類別名稱
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '& $notchedOutline': {
+ '& .MuiOutlinedInput-notchedOutline': {
borderWidth: 1,
}
}
}
}
}
});
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '& $notchedOutline': {
+ [`& .${outlinedInputClasses.notchedOutline}`]: {
borderWidth: 1,
}
}
}
}
}
});
請查看完整的可用全域狀態類別名稱清單。
重構空格和逗號分隔值的替代語法
Emotion 不支援 JSS 支援的空格和逗號分隔值的替代、基於陣列的語法。
將基於陣列的值替換為基於字串的值
之前
const theme = createTheme({
overrides: {
MuiBox: {
root: {
background: [
['url(image1.png)', 'no-repeat', 'top'],
['url(image2.png)', 'no-repeat', 'center'],
'!important',
],
},
},
},
});
之後
const theme = createTheme({
components: {
MuiBox: {
styleOverrides: {
root: {
background:
'url(image1.png) no-repeat top, url(image2.png) no-repeat center !important',
},
},
},
},
});
請務必根據需要為數值新增單位。
之前
const theme = createTheme({
overrides: {
MuiOutlinedInput: {
root: {
padding: [[5, 8, 6]],
},
},
},
});
之後
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
padding: '5px 8px 6px',
},
},
},
},
});
ref
重構非 ref 轉發類別元件
已移除在 component
屬性或作為直接 children
中對非 ref 轉發類別元件的支援。
如果您使用的是 unstable_createStrictModeTheme
或未看到任何與 React.StrictMode
中的 findDOMNode
相關的警告,則您無需採取任何進一步的動作。
否則,請查看組合指南中的關於 refs 的注意事項章節,以了解如何遷移。此變更幾乎影響所有您使用 component
屬性或將 children
傳遞給需要 children
為元素的元件 (例如 <MenuList><CustomMenuItem /></MenuList>
) 的情況。
修正 ref 類型特異性
對於某些元件,當傳遞 ref
時,您可能會收到類型錯誤。為了避免錯誤,您應該使用特定的元素類型。例如,Card
預期 ref
的類型為 HTMLDivElement
,而 ListItem
預期其 ref
類型為 HTMLLIElement
。
以下是一個範例
import * as React from 'react';
import Card from '@mui/material/Card';
import ListItem from '@mui/material/ListItem';
export default function SpecificRefType() {
- const cardRef = React.useRef<HTMLElement>(null);
+ const cardRef = React.useRef<HTMLDivElement>(null);
- const listItemRef = React.useRef<HTMLElement>(null);
+ const listItemRef = React.useRef<HTMLLIElement>(null);
return (
<div>
<Card ref={cardRef}></Card>
<ListItem ref={listItemRef}></ListItem>
</div>
);
}
以下是每個元件預期的特定元素類型
@mui/material
- Accordion -
HTMLDivElement
- Alert -
HTMLDivElement
- Avatar -
HTMLDivElement
- ButtonGroup -
HTMLDivElement
- Card -
HTMLDivElement
- Dialog -
HTMLDivElement
- ImageList -
HTMLUListElement
- List -
HTMLUListElement
- Tab -
HTMLDivElement
- Tabs -
HTMLDivElement
- ToggleButton -
HTMLButtonElement
@mui/lab
- Timeline -
HTMLUListElement
樣式函式庫
✅ 調整 CSS 注入順序
v5 中預設使用的樣式函式庫是 Emotion。
如果您使用 JSS 來覆寫 Material UI 元件的樣式 (例如,由 makeStyles
建立的樣式),則您需要注意 CSS 注入順序。JSS <style
> 元素需要在 Emotion <style>
元素之後注入到 <head>
中。
若要執行此操作,您需要在元件樹狀結構的頂端使用具有 injectFirst
選項的 StyledEngineProvider
,如下所示
import * as React from 'react';
import { StyledEngineProvider } from '@mui/material/styles';
export default function GlobalCssPriority() {
return (
{/* Inject Emotion before JSS */}
<StyledEngineProvider injectFirst>
{/* Your component tree. Now you can override Material UI's styles. */}
</StyledEngineProvider>
);
}
✅ 將 prepend 新增至 createCache
如果您有自訂快取並且使用 Emotion 來樣式化您的應用程式,它將覆寫 Material UI 提供的快取。
若要修正注入順序,請將 prepend
選項新增至 createCache
,如下所示
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
+ prepend: true,
});
export default function PlainCssPriority() {
return (
<CacheProvider value={cache}>
{/* Your component tree. Now you can override Material UI's styles. */}
</CacheProvider>
);
}
主題結構
✅ 新增 adaptV4Theme helper
主題的結構在 v5 中已變更。您需要更新其形狀。為了更順暢地轉換,adaptV4Theme
helper 允許您迭代地將一些主題變更升級到新的主題結構。
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme, adaptV4Theme } from '@mui/material/styles';
-const theme = createMuiTheme({
+const theme = createTheme(adaptV4Theme({
// v4 theme
-});
+}));
適配器支援以下變更
移除 gutters
"gutters" 抽象概念尚未證明其使用頻率足以使其有價值。
-theme.mixins.gutters(),
+paddingLeft: theme.spacing(2),
+paddingRight: theme.spacing(2),
+[theme.breakpoints.up('sm')]: {
+ paddingLeft: theme.spacing(3),
+ paddingRight: theme.spacing(3),
+},
✅ 移除 px 後綴
theme.spacing
現在預設傳回帶有 px 單位的單一值。此變更改善了與 styled-components 和 Emotion 的整合。
之前
theme.spacing(2) => 16
之後
theme.spacing(2) => '16px'
✅ 重新命名 theme.palette.type
theme.palette.type
鍵已重新命名為 theme.palette.mode
,以更好地遵循通常用於描述此功能的「深色模式」術語。
import { createTheme } from '@mui/material/styles';
-const theme = createTheme({ palette: { type: 'dark' } }),
+const theme = createTheme({ palette: { mode: 'dark' } }),
變更預設 theme.palette.info 顏色
預設的 theme.palette.info
顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。
info = {
- main: cyan[500],
+ main: lightBlue[700], // lightBlue[400] in "dark" mode
- light: cyan[300],
+ light: lightBlue[500], // lightBlue[300] in "dark" mode
- dark: cyan[700],
+ dark: lightBlue[900], // lightBlue[700] in "dark" mode
}
變更預設 theme.palette.success 顏色
預設的 theme.palette.success
顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。
success = {
- main: green[500],
+ main: green[800], // green[400] in "dark" mode
- light: green[300],
+ light: green[500], // green[300] in "dark" mode
- dark: green[700],
+ dark: green[900], // green[700] in "dark" mode
}
變更預設 theme.palette.warning 顏色
預設的 theme.palette.warning
顏色已變更為在淺色和深色模式下都通過 AA 無障礙標準對比度。
warning = {
- main: orange[500],
+ main: '#ED6C02', // orange[400] in "dark" mode
- light: orange[300],
+ light: orange[500], // orange[300] in "dark" mode
- dark: orange[700],
+ dark: orange[900], // orange[700] in "dark" mode
}
還原 theme.palette.text.hint 鍵 (如果需要)
theme.palette.text.hint
鍵在 Material UI 元件中未使用,並且已移除。如果您依賴它,您可以將其重新新增
import { createTheme } from '@mui/material/styles';
-const theme = createTheme(),
+const theme = createTheme({
+ palette: { text: { hint: 'rgba(0, 0, 0, 0.38)' } },
+});
重新建構元件定義
主題中的元件定義已在 components
鍵下重新建構,使其更容易找到。
1. props
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
- props: {
- MuiButton: {
- disableRipple: true,
- },
- },
+ components: {
+ MuiButton: {
+ defaultProps: {
+ disableRipple: true,
+ },
+ },
+ },
});
2. overrides
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
- overrides: {
- MuiButton: {
- root: { padding: 0 },
- },
- },
+ components: {
+ MuiButton: {
+ styleOverrides: {
+ root: { padding: 0 },
+ },
+ },
+ },
});
@mui/styles
更新 ThemeProvider 匯入
如果您將 @mui/styles
中的公用程式與 @mui/material
一起使用,則應將 @mui/styles
中的 ThemeProvider
用法替換為從 @mui/material/styles
匯出的用法。
這樣,在上下文中提供的主題將在從 @mui/styles
匯出的樣式公用程式 (例如 makeStyles
、withStyles
等) 以及 Material UI 元件中都可用。
-import { ThemeProvider } from '@mui/styles';
+import { ThemeProvider } from '@mui/material/styles';
請務必在應用程式的根目錄中新增 ThemeProvider
,因為 defaultTheme
在來自 @mui/styles
的公用程式中不再可用。
✅ 為 DefaultTheme 新增模組擴充 (TypeScript)
@mui/styles
套件不再是 @mui/material/styles
的一部分。
如果您將 @mui/styles
與 @mui/material
一起使用,則需要為 DefaultTheme
新增模組擴充。
// in the file where you are creating the theme (invoking the function `createTheme()`)
import { Theme } from '@mui/material/styles';
declare module '@mui/styles' {
interface DefaultTheme extends Theme {}
}
@mui/material/colors
✅ 變更顏色匯入
超過一級的巢狀匯入是私有的。例如,您不能再從 @mui/material/colors/red
匯入 red
。
-import red from '@mui/material/colors/red';
+import { red } from '@mui/material/colors';
@mui/material/styles
✅ 將 fade 重新命名為 alpha
fade()
已重新命名為 alpha()
,以更好地描述其功能。
先前的名稱在輸入顏色已具有 alpha 值時會造成混淆。helper 會覆寫顏色的 alpha 值。
-import { fade } from '@mui/material/styles';
+import { alpha } from '@mui/material/styles';
const classes = makeStyles(theme => ({
- backgroundColor: fade(theme.palette.primary.main, theme.palette.action.selectedOpacity),
+ backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
}));
✅ 更新 createStyles 匯入
來自 @mui/material/styles
的 createStyles
函式已移至從 @mui/styles
匯出的函式。這對於移除 Material UI npm 套件中對 @mui/styles
的依賴性是必要的。
-import { createStyles } from '@mui/material/styles';
+import { createStyles } from '@mui/styles';
✅ 更新 createGenerateClassName 匯入
createGenerateClassName
函式不再從 @mui/material/styles
匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles
套件匯入它。
-import { createGenerateClassName } from '@mui/material/styles';
+import { createGenerateClassName } from '@mui/styles';
若要在不使用 @mui/styles
的情況下產生自訂類別名稱,請查看 ClassName Generator 以了解更多詳細資訊。
✅ 重新命名 createMuiTheme
函式 createMuiTheme
已重新命名為 createTheme()
,使其更直覺地與 ThemeProvider
一起使用。
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme } from '@mui/material/styles';
-const theme = createMuiTheme({
+const theme = createTheme({
✅ 更新 MuiThemeProvider 匯入
MuiThemeProvider
元件不再從 @mui/material/styles
匯出。請改用 ThemeProvider
。
-import { MuiThemeProvider } from '@mui/material/styles';
+import { ThemeProvider } from '@mui/material/styles';
✅ 更新 jssPreset 匯入
jssPreset
物件不再從 @mui/material/styles
匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles
套件匯入它。
-import { jssPreset } from '@mui/material/styles';
+import { jssPreset } from '@mui/styles';
✅ 更新 makeStyles
匯入
由於 Material UI v5 不使用 JSS,因此基於 JSS 的 makeStyles
公用程式不再由 @mui/material/styles
匯出。在將您的應用程式從 JSS 遷移出來時,您可以暫時從 @mui/styles/makeStyles
匯入此已棄用的公用程式,然後再進一步重構您的元件。
請務必在應用程式的根目錄中新增 ThemeProvider
,因為 defaultTheme
不再可用。
如果您將此公用程式與 @mui/material
一起使用,建議您改用 @mui/material/styles
中的 ThemeProvider
元件。
-import { makeStyles } from '@mui/material/styles';
+import { makeStyles } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const useStyles = makeStyles((theme) => ({
background: theme.palette.primary.main,
}));
function Component() {
const classes = useStyles();
return <div className={classes.root} />
}
// In the root of your app
function App(props) {
- return <Component />;
+ return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
}
✅ 更新 ServerStyleSheets 匯入
ServerStyleSheets
元件不再從 @mui/material/styles
匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles
套件匯入它。
-import { ServerStyleSheets } from '@mui/material/styles';
+import { ServerStyleSheets } from '@mui/styles';
styled
由於 Material UI v5 不使用 JSS,因此由 @mui/material/styles
匯出的基於 JSS 的 styled
公用程式已替換為等效的基於 Emotion 的公用程式,該公用程式不向後相容。在將您的應用程式從 JSS 遷移出來時,您可以暫時從已棄用的 @mui/styles
套件匯入基於 JSS 的公用程式,然後再進一步重構您的元件。
請務必在應用程式的根目錄中新增 ThemeProvider
,因為 defaultTheme
不再可用。
如果您將此公用程式與 @mui/material
一起使用,建議您改用 @mui/material/styles
中的 ThemeProvider
元件。
-import { styled } from '@mui/material/styles';
+import { styled } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const MyComponent = styled('div')(({ theme }) => ({ background: theme.palette.primary.main }));
function App(props) {
- return <MyComponent />;
+ return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
}
✅ 更新 StylesProvider 匯入
StylesProvider
元件不再從 @mui/material/styles
匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles
套件匯入它。
-import { StylesProvider } from '@mui/material/styles';
+import { StylesProvider } from '@mui/styles';
✅ 更新 useThemeVariants 匯入
useThemeVariants
Hook 不再從 @mui/material/styles
匯出。如果您需要繼續使用它,可以從已棄用的 @mui/styles
套件匯入它。
-import { useThemeVariants } from '@mui/material/styles';
+import { useThemeVariants } from '@mui/styles';
✅ 更新 withStyles 匯入
由於 Material UI v5 不使用 JSS,因此基於 JSS 的 withStyles
公用程式不再由 @mui/material/styles
匯出。在將您的應用程式從 JSS 遷移出來時,您可以暫時從 @mui/styles/withStyles
匯入此已棄用的公用程式,然後再進一步重構您的元件。
請務必在應用程式的根目錄中新增 ThemeProvider
,因為 defaultTheme
不再可用。
如果您將此公用程式與 @mui/material
一起使用,則應改用 @mui/material/styles
中的 ThemeProvider
元件。
-import { withStyles } from '@mui/material/styles';
+import { withStyles } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const defaultTheme = createTheme();
const MyComponent = withStyles((props) => {
const { classes, className, ...other } = props;
return <div className={clsx(className, classes.root)} {...other} />
})(({ theme }) => ({ root: { background: theme.palette.primary.main }}));
function App() {
- return <MyComponent />;
+ return <ThemeProvider theme={defaultTheme}><MyComponent /></ThemeProvider>;
}
✅ 將 innerRef 替換為 ref
將 innerRef
屬性替換為 ref
屬性。Refs 現在會自動轉發到內部元件。
import * as React from 'react';
import { withStyles } from '@mui/styles';
const MyComponent = withStyles({
root: {
backgroundColor: 'red',
},
})(({ classes }) => <div className={classes.root} />);
function MyOtherComponent(props) {
const ref = React.useRef();
- return <MyComponent innerRef={ref} />;
+ return <MyComponent ref={ref} />;
}
更新 withTheme 匯入
withTheme
HOC 公用程式已從 @mui/material/styles
套件中移除。您可以改用 @mui/styles/withTheme
。
請務必在應用程式的根目錄中新增 ThemeProvider
,因為 defaultTheme
不再可用。
如果您將此公用程式與 @mui/material
一起使用,建議您改用 @mui/material/styles
中的 ThemeProvider
元件。
-import { withTheme } from '@mui/material/styles';
+import { withTheme } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const MyComponent = withTheme(({ theme }) => <div>{theme.direction}</div>);
function App(props) {
- return <MyComponent />;
+ return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
}
✅ 移除 withWidth
此 HOC 已移除。如果您需要此功能,可以嘗試使用 useMediaQuery
Hook 的替代方案。
@mui/icons-material
縮小 GitHub 圖示大小
GitHub 圖示的大小已從 24px 寬縮小為 22px 寬,以符合其他圖示的大小。
@material-ui/pickers
我們有一個專門頁面用於將 @material-ui/pickers
遷移至 v5。
系統
✅ 重新命名 gap 屬性
以下系統函式和屬性已重新命名,因為它們被視為已棄用的 CSS
gridGap
變為gap
gridRowGap
變為rowGap
gridColumnGap
變為columnGap
✅ 將間距單位新增至 gap 屬性
在 gap
、rowGap
和 columnGap
中使用間距單位。如果您先前使用的是數字,則需要提及 px 以繞過使用 theme.spacing
的新轉換。
<Box
- gap={2}
+ gap="2px"
>
將 css
屬性替換為 sx
,以避免與 styled-components 和 Emotion 的 css
屬性發生衝突。
-<Box css={{ color: 'primary.main' }} />
+<Box sx={{ color: 'primary.main' }} />