我正在使用Material UI v4,我正在从一个文件中导出样式, 但是样式不能在其他组件中使用 styles.js
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
},
// textField component styles
textFieldInput: {
margin: theme.spacing(2),
width: 250,
minWidth: 250,
},
formControl: {
margin: theme.spacing(2),
minWidth: 120,
},
})
export {useStyles}
在我的组件文件中
....
const classes = useStyles(styles);
return (
<TextField
className={classes.textFieldInput}
label={label}
placeholder={label}
error={touched && invalid}
helperText={touched && error}
{...input}
disabled={disabled || false}
readOnly={readOnly || false}
required={required || false}
InputProps={{ readOnly, ...custom }}
{...custom}
/>
);
....
当我在组件中使用它时 样式将在第一次热装时工作,但是之后样式将不会产生任何影响,为什么?以及如何解决这个问题
答案 0 :(得分:1)
如果您将两个CSS类以相同的特异性程度应用于同一元素,那么获胜者将是该文档中最后定义的CSS类(基于<style>
元素在文档中的顺序<head>
,否在要设置样式的元素的class
属性中类名称字符串的顺序。)
This page是带有两个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
类将应用于与通过TextField的className
属性指定的类相同的元素(例如,makeStyles/useStyles
中的textFieldInput类)。由于MuiFormControl <style>
元素出现在makeStyles
<style>
元素之后,因此MuiFormControl的margin
和min-width
的默认样式将胜过{{1}指定的自定义样式}。
这些makeStyles
元素的顺序由<style>
的调用顺序控制。对于给定的Material-UI组件的默认样式,makeStyles
在首次导入该组件时被调用。
对于典型的用法模式,在同一JavaScript文件中调用makeStyles
,然后调用makeStyles
并将类传递给Material-UI组件,顺序将始终是您想要的,因为Material-UI组件的导入将在调用useStyles
之前进行。
当您将对makeStyles
的调用移到一个单独的文件并导入其返回的makeStyles
方法时,就会引入导入useStyles
的可能性,之前导入Material-UI组件(在这种情况下,例如TextField)。
以下沙箱中的代码演示了这一点:https://codesandbox.io/s/makestyles-first-i1mwh
它可能在第一次热重装上起作用的原因是,useStyles
makeStyles
元素已被删除,然后在进行更改时添加到末尾。 Mui *样式元素不会更改,因此它们会保留在原处(在新的<style>
样式元素之前,直到重新加载页面为止)。
由于makeStyles
在withStyles
中被调用,因此您无法轻易地使用Higher-order component API(即makeStyles
)以这种方式射击自己的脚,因此您将始终导入withStyles
包装的组件,然后再将其作为参数传递。
有几种方法可以解决此问题。一种方法是仅确保在导入Material-UI组件(例如withStyles
后后导入useStyles
函数。
更改:
TextField
改为:
import { useStyles } from "./styles";
import TextField from "@material-ui/core/TextField";
这在这里得到证明:https://codesandbox.io/s/import-textfield-first-9qybd
这是相当脆弱的,但是如果您在import TextField from "@material-ui/core/TextField";
import { useStyles } from "./styles";
中具有一种以上类型的组件的样式并从许多文件中导入styles.js
,因为要使其可靠地工作,您就必须依赖导入styles.js的第一个位置之前,由styles.js
设置样式的Material-UI组件的所有。
解决此问题的另一种方法是导出Material-UI组件的样式版本,而不是导出styles.js
函数。然后,您只需导入此自定义组件而不是Material-UI组件即可。
useStyles
在此处有两个不同的语法选项对此进行了演示:https://codesandbox.io/s/import-styled-textfield-1ytxl
答案 1 :(得分:0)
我遇到了类似的问题,并设法解决了以下问题
root: {
'&&': {
width: "128px",
height: "128px",
margin: "8px",
}
},
我后来还发现了一篇关于这个 here 的文章。
使用双与号“&&”会增加/加倍特异性/优先级。 因此,对于我想覆盖的任何类,我在声明的类中添加了“&&”。
这为我解决了问题,没有任何明显的缺点,但我不知道这是否真的是一个好习惯。如果有人知道更多关于为什么不使用它的信息,请告诉我。