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

Scss module (css modules): importing from other scss files

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

假设我有一个组件 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.
}

现在我有了另一个组件 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;
        }
    }
}

请注意,我仍在使用 .button 来定位各个按钮。但这不会起作用,因为子组件实际上并没有 .button 作为其 class 名称,因为它是生成的唯一 class 名称。

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

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

  • 解决方案 #1:从不共享 class 名称,co-locating 样式属于一起并在相同的 class 名称上运行。 在您的情况下,这意味着您只有一个与按钮 buttons.modules.scss 相关的 scss 文件,并且 Button.jsButtonGroup.js 都导入它。
  • 解决方案 #2:通过将共享 class 名称标记为 :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
}
// 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; }
    }
}
  • 解决方案 #3:接受匿名 children。 child人的class姓名可以省略。没有人将 non-buttons 放在按钮组中(甚至可能在您的组件代码中强制执行)。
// 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; }
    }
}
  • 解决方案 #4:从另一个文件引用内容。似乎有一些支持可以 reference/import 来自其他文件的语法,但我仔细阅读了文档和一些 github 问题讨论 'import className from fileName' 'more' 'and more' without getting any clear answer as to how one would import a local classname from another file. There might be something possible either along those lines see here:
@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; }
    }
}

...或沿着这些线 see here:

: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; }
    }
}
  • 解决方案 #5:让您的容器组件向每个 child 添加一个 class .button-group-item 并使用它来应用边距而不是 .button class.