使用 SASS 类覆盖 Material UI 组件

Posted

技术标签:

【中文标题】使用 SASS 类覆盖 Material UI 组件【英文标题】:Override Material UI component with SASS classes 【发布时间】:2018-09-02 07:13:07 【问题描述】:

我正在使用 Material UI 组件,但想将我的所有样式移动到 .scss 文件中。目前,我在使用 Material UI 组件的同一个 javascript 文件中有一个大型样式对象。此样式对象通过 style 属性传递给 Material UI 组件。在我看来,这或多或少只是内联样式,我的目标是消除这种模式。我在这些 Material UI 组件中有其他嵌套组件(Material UI 组件以及自定义 React 组件)。这是我正在使用的示例:

 const styles= //all my css styles in here

<TableRowColumn key=index style=styles.column>
     <span className="checkbox-thing">
       <input
         ....
       />
     </span>
</TableRowColumn>

我已经参考了覆盖文档:https://material-ui-next.com/customization/overrides/

还有这个 Stack Overflow 问题:How to style material ui next components with styled components and SASS

在我看来,这两个都没有明确说明如何使用外部.scss(样式所在的位置)并将该文件中的类名引用到 Material UI 组件中。我只是为了能够做这样的事情,目前使用普通的 html 元素很容易做到这一点:

<input   
    type="checkbox"
    checked=
      this.props.isChecked
    
    className="someClassInTheSCSSFile"
/>

总之我想:

将我的大型样式对象移除到单独的类中,放入.scss 文件中

.scss 文件中引用一个类并将其弹出到 Material UI 组件中

【问题讨论】:

【参考方案1】:

我不知道为什么它现在开始工作,而不是我之前尝试过的时候,但使用 className="someClassInTheSCSSFile" 最终工作,只要我的 .scss 文件包含类似的内容:

//.scss file

.someClassInTheSCSSFile 
   color: blue;
   //rest of the styles go here

总之,直接在 MATERIAL UI 组件中使用 className 属性是可行的。因此,使用我的问题中的示例代码可以实现以下工作:

//Javascript file

<TableRowColumn key=index className="someClassInTheSCSSFile">
 <span className="checkbox-thing">
   <input
     ....
   />
 </span>
</TableRowColumn>

现在,真正有趣(但令人失望)的是当您想将值传递给 CSS 时。例如,假设这个TableRowColumn 组件有一个width 属性,但我不想将它硬编码到我的.scss 文件中。坚持我不使用任何内联样式的模式,这是一个挑战。让我们说这个TableRowColumn 组件在一个函数内部,该函数接受一个名为colWidth 的参数。当调用该函数时,我想将这个colWidth 值动态传递到我的这个TableRowColumn 组件的css width 属性中。然而,据我所知,这最终成为目前不可能完成的任务。可以做的是:

//Javascript File

<TableRowColumn key=index style=width:`$coldWidth` className="someClassInTheSCSSFile">
 <span className="checkbox-thing">
   <input
     ....
   />
 </span>
</TableRowColumn>

但这是内联样式。正是我试图避免的。所以现在,我最终拥有了内联样式和引用我的.scss 文件的className。可以说更加笨重和繁重。如果我在.scss 中使用attr() 函数怎么样?好吧,根据 MDN (https://developer.mozilla.org/en-US/docs/Web/CSS/attr),这将只支持传递的字符串,而主流浏览器不支持所有其他类型。哎哟。请参阅此代码笔 (https://jsfiddle.net/hmr0hckf/131/) 以获取此操作的示例。故事的寓意是,对于我想要动态更改值的任何 css 属性,我都坚持使用内联样式。

【讨论】:

【参考方案2】:

带有 node-sass 和 sass-loader 的 Webpack

你已经很接近了。像往常一样,将所有样式放入一个或多个 .scss 文件中。例如,一个名为“nodeContent”的类。

.nodeContent 
   position: absolute;
   top: 0;
   bottom: 0;
   display: flex;
   align-items: center;

您需要做的就是导入您的样式并访问类名作为您的样式对象的属性。请参阅下面的示例,我在与我的组件相同的目录中有一个名为 styles.scss 的 Sass 文件。在我的组件中,我可以像这样导入它们:

import * as styles from './styles.scss'

样式是一个对象,我可以像引用对象的任何其他属性一样引用我的类。因此,如果我想在材质组件上使用 nodeContent 类,我可以这样做:

<Card className=styles.nodeContent />

不使用 webpack(不是 100% 确定)

我认为您可以将 .scss 文件编译为 .css 并将它们作为 index.html 文件中的 a 引用。之后,我认为您应该能够像上面显示的那样将 classNames 引用为字符串。 这是我刚刚读到的类似的文章,除了它们在其组件中导入 css 文件:https://hackernoon.com/using-sass-with-create-react-app-without-ejecting-b5f4f827ed9e

【讨论】:

这样直接导入我的.scss就是给我一个404 嗯...有趣。你在用 webpack 吗? 我没有使用 webpack 我明白了。我假设您正在使用带有 node-sass 和 sass-loader 的 webpack,我的错。在您的情况下,我认为您可以将 .scss 文件编译为 .css 并将它们作为 index.html 文件中的 引用。之后,我认为您应该能够像上面显示的那样将 classNames 引用为字符串。这是我刚刚读到的类似的文章,只是它们在其组件中导入了 css 文件。 hackernoon.com/… 参考我更新的答案。结果很失望,还是谢谢你。

以上是关于使用 SASS 类覆盖 Material UI 组件的主要内容,如果未能解决你的问题,请参考以下文章

让 svelte-material-ui 与 snowpack 和 sass 一起使用

设置 Material UI 套件 React 时,Sass-Loader 的模块构建失败

如何从祖先覆盖嵌套 Material UI 组件的样式?

javascript 版本0.x的Material-UI排版(基于SASS和CSS模块)

Material UI v1.0.0 如何覆盖 Stepper 类来设置图标大小

Material-UI:“提供给类属性的键未实现”