scss模块(css module):从其他scss文件导入

Sam*_*Liu 2 css sass css-modules

我目前正在将 sass 样式转换为使用css 模块以避免样式冲突。我的理解是,它会生成唯一的类名,这使得如果我想定位在不同文件中定义的另一个组件(例如子组件)会变得很困难。

假设我有一个组件Button,它从Button.module.scss文件导入:

// Button.js
import styles from "./Button.module.scss";

export const Button () => <button className={styles.button} />;

// Button.module.scss
.button {
    // relevant styles.
}
Run Code Online (Sandbox Code Playgroud)

现在我有了另一个组件ButtonGroup。假设我想让组中的按钮在它们之间有边距,我会有这样的东西:

// ButtonGroup.module.scss
.buttonGroup {
    display: flex
    &[class~=horizontal] {
        & > .button:not(:first-child) { // still using the same class name
            margin-left: 1rem;
        }
    }
    &[class~=vertical] {
        flex-direction: column;
        & > .button:not(:first-child) { // still using the same class name
            margin-top: 1rem;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我仍然使用.button来定位各个按钮。但这是行不通的,因为子组件实际上没有.button类名,因为它是生成的唯一类名。

我可以使用类似 [class^=Button] 的东西,但是一旦你有很多组件,这感觉很老套并且很难维护。(还意识到它在生产中不起作用。)

Mar*_*tin 9

css-modules与 SASS 或 SCSS 无关,并且有自己的一组支持的功能和关键字。是的,它们可以一起使用,我在大多数项目中实际上都是这样做的。但我避免不同文件之间存在类名依赖关系。我知道一些可用于共享类名的功能,但避免使用它可能是最好的解决方案。我将在下面的部分列出我能想到的解决您的难题的所有潜在解决方案;选择最适合您的:

  • 解决方案#1:永远不要共享类名,将属于一起并在相同类名上运行的样式放在一起。在您的情况下,这意味着您只有一个buttons.modules.scss与按钮相关的 scss 文件Button.js,然后ButtonGroup.js将其导入。
  • 解决方案#2:通过将共享类标记为:global. 这可以这样完成:
// button.module.scss

// this will stay a global classname
:global(.button) {
    // the button styles
}

// this will be treated as usual, generating a local name
.icon {
    // some icon stuff
}
Run Code Online (Sandbox Code Playgroud)
// buttongroup.module.scss
.buttonGroup {
    display: flex;

    // will be resolved as local classname
    &.horizontal {
        flex-direction: row;
        // will be resolved as global classname
        & > :global(.button):not(:first-child) { margin-left: 1rem; }
    }
    &.vertical {
        flex-direction: column;
        & > :global(.button):not(:first-child) { margin-top: 1rem; }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 解决方案#3:接受匿名儿童。您可以省略子级的类名。没有人会将非按钮放在按钮组中(甚至可能在组件代码中强制执行它)。
// buttongroup.module.scss
.buttonGroup {
    display: flex;

    &.horizontal {
        flex-direction: row;
        & > *:not(:first-child) { margin-left: 1rem; }
    }
    &.vertical {
        flex-direction: column;
        & > *:not(:first-child) { margin-top: 1rem; }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 解决方案#4:引用另一个文件的内容。似乎有一些支持可以从其他文件引用/导入内容的语法,但我仔细阅读了文档和一些 github 问题讨论“从文件名导入类名” “更多” “更多”,但没有得到任何明确的答案如何从另一个文件导入本地类名。沿着这些思路可能有一些可能,请参见此处
@import button from './button.module.scss';
.buttonGroup {
    display: flex;

    &.horizontal {
        flex-direction: row;
        & > .button:not(:first-child) { margin-left: 1rem; }
    }
    &.vertical {
        flex-direction: column;
        & > .button:not(:first-child) { margin-top: 1rem; }
    }
}
Run Code Online (Sandbox Code Playgroud)

...或者沿着这些思路看这里

:import("./button.module.scss") {
  imported-button: button;
}

.buttonGroup {
    display: flex;

    &.horizontal {
        flex-direction: row;
        & > .imported-button:not(:first-child) { margin-left: 1rem; }
    }
    &.vertical {
        flex-direction: column;
        & > .imported-button:not(:first-child) { margin-top: 1rem; }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 解决方案#5:让您的容器组件.button-group-item向每个子组件添加一个类,并使用它来应用边距而不是类.button