【问题标题】:Sass use classname from other .scss fileSass 使用其他 .scss 文件中的类名
【发布时间】:2020-11-28 02:17:18
【问题描述】:

大家好,

我想知道是否有办法以共享类名的方式链接 .scss。

这就是我想要实现的目标。

|- theme
|   |- theme_default.scss
|- snippets
|   |-componentA
|   |   |-componentA.js
|   |   |-componentA.scss

ComponentA.js 文件中,我使用 css-loader/CommonJS 将一个类从 ComponentA.scss 附加到组件(如果有人需要知道,我正在使用 webpack 开发环境)。

theme_default.scss 中,我尝试将主题样式应用于“ComponentA”。默认主题文件应该可以被其他主题文件交换。

问题是类名(即使在源文件中相同)在编译成常规的“.css”文件时会被散列,这意味着主题 cssfile 中的类名永远不会匹配来自主题 css 文件的类名组件一个 cssfile。

那么我怎样才能明确主题文件应该使用与组件文件相同的类名而不将样式声明为global?我尝试在主题文件中使用@import@use,但它只复制规则,而类名仍然不相同。

欢迎任何意见,提前感谢阅读。

编辑


根据要求提供一些示例

theme_default.scss

.theme_default {
   .comp_a /* This class should be the same (hashed) as in the componentA.scss */ {
      background-color: red; /* awefull, but just for example sake */
   }
}

组件A.scss

.comp_a {
   display: flex;
   flex-wrap: no-wrap;
   /*.. etc.*/
}

componentA.js

import style from './componentA.scss'

// this is how I set the style, but this class does NOT know about any theme stylesheet. So nothing can be done from here
element.classList.add(style.comp_a);

为了应用主题,我将theme_default 类(哈希版本)设置为根元素,并让浏览器找出如何有效地(重新)呈现它。

我读到 css-loader 有一个带有compose(s) 的机制,它可能会解决这个问题。但它似乎不适用于 webpack 或 vsCode。所以无论如何有人需要它,这里是 webpack 配置文件中关于 css 处理的 sn-p。

webpack.configuration.js

{
    test: /\.s[ac]ss$/i,
    include: [
        path.resolve(__dirname, 'src')
    ],
    exclude: [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, 'build'),
            path.resolve(__dirname, 'test'),
    ],
    use: [
        // Creates `style` nodes from JS strings
        isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
        // Translates CSS into CommonJS
        {
            loader: 'css-loader',
            options:
            {
                modules:
                {
                    exportGlobals: true,
                },
                importLoaders: 2,
                sourceMap: isDevelopment,
            }
        },
        // Transform urls
        {
            loader: 'resolve-url-loader',
            options:
            {
                sourceMap: isDevelopment
            }
        },
        // Compiles Sass to CSS
        {
            
            loader: 'sass-loader',
            options:
            {
                sassOptions:
                {
                    indentWidth: 4,
                    sourceMap: isDevelopment,
                    sourceMapContents: false,
                    outputStyle: 'expanded'
                },
            },
        }
    ],
},

【问题讨论】:

  • 您能否举一个theme_default.scss 中的规则示例以及您如何使用ComponentA.js 中的类名?我觉得这可能是一个与 CSS Modules/bundler 相关的问题,而不是 Sass
  • @Coogan 这足以继续,还是您需要更多/其他信息?
  • 我想是的。希望我能帮助你解决这个问题

标签: css webpack sass css-loader sass-loader


【解决方案1】:

使用 CSS 模块时主题化有点棘手,因为它的目的是创建不受 CSS 级联影响的本地范围的 CSS。

话虽如此,一些选项可供您选择,具体取决于您想采取的路线。


论据/道具主题

因为 CSS 模块不希望受到级联的影响,所以很难通过使用 DOM 树中更高的类名来更改组件级 CSS。 CSS-Modules 项目确实有一个page on theming,但我认为这与您尝试实现样式的方式有些不同。不过,我鼓励你考虑一下。

他们的方法是为每个组件创建一个主题样式表,然后将它们导入到所述组件中,根据变量切换您要使用的样式表。在 React 中,这将是一个 prop

dark.css

.button {
  border: 1px solid #333;
}

neon.css

.button {
  border: 1px solid #0f0;
}

Button.js

export default class Button {
  constructor(theme) {
    this.theme = theme;
  }
  render() {
    const theme = this.theme;
    return `<div class="${theme.button}">Hello World</div>`;
  }
}

app.js

import darkTheme from "./dark.css";
import neonTheme from "./neon.css";

import Button from "./button";

// use component
new Button(dark);
new Button(neon);

这种方法更倾向于传统的 CSS 模块方法,在这种方法中,您将在源代码中复制一些样式,但您可以通过减少交付给客户端的内容来弥补它。

与 Sass 一起使用

由于您使用的是 Sass,因此您可以通过使用Sass Mixins 来减少将来更改事物的重复和繁琐。

如果您有一组 CSS 属性,这些属性在将使用它们的许多组件(background-colorborder-color 等)中通用,并且允许您将这些规则集中到一个文件中,这将特别有用它们可以更改并在其他文件中传播。

themes.scss

@mixin neon {
  background-color: #0f0;
  border: 2px solid #ff0;
  color: #000;
}

按钮/neon.scss

.button {
  @include neon;
}

// Or, if you're using the latest Dart Sass and its @use rule
@use "themes";

.button {
  @include themes.neon;
}

这仍然需要您将主题设置为应用程序变量并将其作为 arg 或 prop 传递,但应该减少您在每个文件中复制 CSS 规则的需要。


CSS 自定义属性

您可以使用的替代路径if your browser support allows it 是使用CSS Custom Properties。这将允许您从外部控制 CSS 模块生成的类名中的值。

style.css

.button {
  background-color: var(--button-bg, #900); /* #900 default fallback if --button-bg doesn't exist*/
}

app.css

body {
  --button-bg: #f48024;
}

body.dark {
  --button-bg: #a34d08;
}

【讨论】:

  • 感谢您的回答。我也在 SASS 本身的网站上找到了第一个选项。不幸的是,它使系统变得僵化(之后更改主题会很乏味,我想比单个 css 类更改要慢得多)。但如果没有好的选择,我必须考虑实施它。您的第二个建议可能是一个有效的方法(尤其是使用后备颜色)。我会看看我能想出什么,谢谢你的时间
  • 可以理解。我同意 CSS Modules 系统在其实现中有些限制,但在试图避免级联时,这些事情是必要的。话虽这么说,我已经使用 Sass 中可用的方法更新了答案,这可以帮助缓解您在 CSS 模块中重复遇到的问题/担忧
  • 这可能是一个不错的解决方案,尤其是因为您可以动态地“编程”它。我会让每个选项运行,看看什么最适合。
  • 您是否可以使用任何方法作为解决方案,@n247s
  • 我还不能继续主题化。该项目的其他部分目前具有优先权。一旦我实施了解决方案,我会尽量记住报告。
猜你喜欢
  • 1970-01-01
  • 2020-01-28
  • 2018-09-23
  • 1970-01-01
  • 2018-02-12
  • 1970-01-01
  • 2016-03-24
  • 2015-03-20
  • 2016-12-12
相关资源
最近更新 更多