为什么会这样?
如果您将两个 CSS 类应用于具有相同特定程度的同一元素,那么获胜者将是文档中最后定义的 CSS 类(基于 中<style>
元素的顺序<head>
,而不是类的顺序class
正在设置样式的元素的属性中的名称字符串)。
此页面是一个带有两个 TextField 元素的示例,可重现您的问题。如果您打开浏览器开发人员工具并查看<style>
元素,您会看到makeStyles
样式来自TextField
(例如 MuiFormControl),然后是样式。我在下面展示了一个缩写版本:
<style data-jss="" data-meta="makeStyles">
.makeStyles-textFieldInput-1 {
margin: 32px;
min-width: 250px;
}
</style>
<style data-jss="" data-meta="MuiFormControl">
.MuiFormControl-root {
border: 0;
margin: 0;
display: inline-flex;
padding: 0;
position: relative;
min-width: 0;
flex-direction: column;
vertical-align: top;
}
.MuiFormControl-marginNormal {
margin-top: 16px;
margin-bottom: 8px;
}
.MuiFormControl-marginDense {
margin-top: 8px;
margin-bottom: 4px;
}
.MuiFormControl-fullWidth {
width: 100%;
}
</style>
<style data-jss="" data-meta="MuiTextField">
</style>
所述MuiFormControl-root
类被施加到经由文本域的指定的类相同的元件className
特性(例如,从textFieldInput类makeStyles/useStyles
)。由于MuiFormControl<style>
元素后出现makeStyles
<style>
元素,MuiFormControl的默认样式margin
和min-width
拉拢由造型指定的自定义makeStyles
。
这些<style>
元素的顺序由makeStyles
调用的顺序控制。对于给定 Material-UI 组件的默认样式,makeStyles
在第一次导入组件时调用。
对于典型的使用模式, wheremakeStyles
在同一个 JavaScript 文件中调用,然后调用useStyles
并将类传递给 Material-UI 组件,顺序将始终是您想要的,因为 Material-UI 组件的导入将在调用之前发生到makeStyles
。
当您将调用移动makeStyles
到一个单独的文件并导入useStyles
它返回的方法时,您引入了useStyles
在导入 Material-UI 组件之前导入的可能性(例如本例中的 TextField)。
这在此沙箱中的代码中进行了演示:https : //codesandbox.io/s/makestyles-first-i1mwh
它可能在第一次热重载时起作用的原因是该makeStyles
<style>
元素被删除,然后在您进行更改时添加到最后。Mui* 样式元素不会更改,因此它们保持原样(在makeStyles
重新加载页面之前,在新样式元素之前)。
使用高阶组件 API(即withStyles
),您不能以这种方式轻松地用这种方式射击自己,因为它makeStyles
是在内部调用的,withStyles
因此withStyles
在将其作为参数传递之前,您将始终导入被包装的组件。
我怎样才能解决这个问题?
有几种方法可以解决这个问题。一种方法是仅仅确保您导入useStyles
功能后,进口材料的UI组件,例如TextField
。
改变:
import { useStyles } from "./styles";
import TextField from "@material-ui/core/TextField";
改为:
import TextField from "@material-ui/core/TextField";
import { useStyles } from "./styles";
这在这里演示:https : //codesandbox.io/s/import-textfield-first-9qybd
这是相当脆弱的,但是如果您有多种类型的组件的样式styles.js
并styles.js
从许多文件中导入,那么为了让它可靠地工作,您依赖于导入所有styles.js
在第一个位置之前设置样式的 Material-UI 组件您导入的styles.js
.
解决此问题的另一种方法是导出 Material-UI 组件的样式版本,而不是导出useStyles
函数。然后你只需导入这个自定义组件而不是 Material-UI 组件。
import { withStyles } from "@material-ui/core/styles";
import MuiTextField from "@material-ui/core/TextField";
const styles = theme => ({
root: {
margin: theme.spacing(4),
minWidth: 250
}
});
export const TextField = withStyles(styles)(MuiTextField);
这在此处通过几个不同的语法选项进行了演示:https : //codesandbox.io/s/import-styled-textfield-1ytxl