使用 Sass/Scss 中的 @use 规则覆盖大量 !default 值

dav*_*ave 3 sass

我有一个带有大量可重写!default变量的 SCSS 模块,并且我尝试在项目中使用新@use规则而不是要弃用的@import. 过去,覆盖大量变量非常简单。只要我在导入模块之前导入变量,它们就会优先于值!default


现在,如果我尝试像这样在全局命名空间中使用@use模块:

$h1-font-size: 40px;

@use 'my-module' as *;
Run Code Online (Sandbox Code Playgroud)

我收到一个错误 - SassError: This module and the new module both define a variable named "$h1-font-size".


显然,执行此操作的正确方法是使用with像这样的关键字

@use 'my-module' with (
    $h1-font-size: 40px
);
Run Code Online (Sandbox Code Playgroud)

但现在我的$h1-font-size变量不可用于代码的其他部分。它的唯一范围是覆盖模块中的值。如果我尝试将它分配给其他东西,我会收到未定义的变量错误。


所以这让我这样做

$h1-font-size: 40px;

@use 'my-module' with (
    $h1-font-size: $h1-font-size
);

.foo {
    font-size: $h1-font-size;
}
Run Code Online (Sandbox Code Playgroud)

这正是我想要的效果 - 一个覆盖我的模块并且仍然可以在其他地方使用的变量。然而,这种语法对于传递大量覆盖来说很麻烦。如果我想传递 30 个覆盖,我需要 30 个变量定义,然后在块中使用 30 行with来显式传递 30 个值。


更新/编辑

下面@Miriam Suzanne 的回答表明我为了提出问题而过度简化了我的用例。

我们的商店有一套在许多项目中使用的 mixin 和基本样式,我一直在尝试将它们变成可重用的模块以减少复制/粘贴。像 Bootstrap 这样的东西,有很多可重写的!default值。这是一项正在进行的工作,但模块本身可以在这里看到:Derekstrap

该模块是与我们实际使用的第一个项目同时开发的。这些!default值都在模块中,我想在我的项目中覆盖它们。

现在我的代码main.scss(样式表的主要入口点)看起来像这样。

$base-font-family: 'Raleway', Tacoma, sans-serif;
$base-line-height: 1.8;

@use '~@evanshunt/derekstrap/index' with (
    $base-font-family: $base-font-family,
    $base-line-height: $base-line-height
);
Run Code Online (Sandbox Code Playgroud)

我喜欢非常精细地构建我的 scss 文件,因此理想情况下这些变量实际上应该存在于另一个文件中,并且也可用于项目中的其他文件。

如果我执行如下操作,其中我的变量文件和模块都$base-font-family定义了变量,则它会进行编译,但变量不会覆盖模块。

@use 'variables' as *;
@use '~@evanshunt/derekstrap/index' as *;
Run Code Online (Sandbox Code Playgroud)

我怀疑此时的答案是我需要向我的变量文件添加@use和/或@forward语句,但是弄清楚我是否能够成功地覆盖模块的不同部分,这让我有点伤脑筋。我的项目代码的不同部分。上面仅使用一个变量文件的建议也是一种简化。@use如果我在main.scss正在修改的文件中修改相同的命名空间,那么my 中的语句顺序将变得多么重要@use


我的目的是显式地确定范围和传递值,但我喜欢某种速记或技巧来完成此任务,而无需编写那么多额外的代码。正如我的 Sass功能请求票中所提到的,我希望有一种简单的速记方式可以将一个上下文传递到另一个上下文中,例如:

@use 'variables' as variables;
@use 'module' with variables;
Run Code Online (Sandbox Code Playgroud)

这似乎不可能,我想知道是否需要完全重新思考构建 SCSS 文件的方式来实现我想要的。我在这里能做什么?

Mir*_*nne 7

当您说变量“不可用于我的代码的其他部分”时,我并不完全清楚您的意思。的全部目的@use是使这些变量在命名空间内可用 \xe2\x80\x93 。所以你可以这样做:

\n
@use \'module\' with (\n    $h1-font-size: 40px\n);\n\n.foo {\n    font-size: module.$h1-font-size;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或使用以下命令删除名称空间as *

\n
@use \'module\' as * with (\n    $h1-font-size: 40px\n);\n\n.foo {\n    font-size: $h1-font-size;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

或在添加配置的同时转发模块,以在其他文件中使用:

\n
@forward \'module\' with (\n    $h1-font-size: 40px !default\n);\n
Run Code Online (Sandbox Code Playgroud)\n

或同时两者:

\n
@forward \'module\' with (\n    $h1-font-size: 40px !default\n);\n\n@use \'module\';\n\n.foo {\n    font-size: module.$h1-font-size;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我认为这可能涵盖了您可能再次定义同一变量的所有潜在用例?

\n
\n

回应问题的更新\xe2\x80\xa6

\n

使用模块语法意味着跨文件没有全局作用域。这意味着每个单独的文件都需要明确@use该文件所需的任何和所有模块。这意味着:

\n
    \n
  • 您将需要@use \'~@evanshunt/derekstrap/index\'(或类似的)在每个应该有权访问 Derekstrap mixins、变量或函数的文件的顶部
  • \n
  • 由于index文件是自动导入的,并且默认名称空间是根据路径生成的,我可能会@use \'~@evanshunt/derekstrap\'改为\xe2\x80\xa6
  • \n
  • 命名空间始终位于导入文件的本地,因此您可以@use \'~@evanshunt/derekstrap\'在一个地方(创建derekstrap命名空间),@use \'~@evanshunt/derekstrap\' as *在另一个地方(删除命名空间),并且仍然@use \'~@evanshunt/derekstrap\' as derek在第三个位置。
  • \n
\n

目标是!default是可以在任何编译之前预先配置它们。这必须在“第一次”使用模块时发生。如果您想在一个文件中单独执行此操作,您可以:

\n
// _config.scss\n@use \'~@evanshunt/derekstrap\' with (\n  $h1-font-size: 40px,\n);\n\n// main.scss\n@use \'config\'; // keep this path first...\n@use \'anything-else\';\n\n// _anything-else.scss\n@use \'~@evanshunt/derekstrap\';\n// derekstrap.$h1-font-size will already be configured by config.scss\n
Run Code Online (Sandbox Code Playgroud)\n

这些值只能预配置一次 - 这意味着编译将从配置值开始。但您可以随时在任何文件中更新这些变量:

\n
// _anything-else.scss\n@use \'~@evanshunt/derekstrap\';\n\nderekstrap.$h1-font-size: 32px;\n// The $h1-font-size now has a value of 32px\n// for any file to uses derekstrap later in the compilation\n
Run Code Online (Sandbox Code Playgroud)\n

在我的网站上,我结合使用了两种方法 - 就在我的一种颜色配置文件中:

\n

https://github.com/mirisuzanne/mia/blob/main/src/scss/config/_color.scss

\n

我有@use \xe2\x80\xa6 with配置的模式cascading-color-systems,但我也使用accoutrement没有配置的工具,然后覆盖tools.$colors

\n

通过添加转发层,您可能会变得更加复杂,但这应该可以帮助您入门。记住:

\n
    \n
  • 该变量$h1-font-size存在于\'~@evanshunt/derekstrap\'模块内部。
  • \n
  • 该模块可以多次使用,并且每次都给出不同的名称空间。该模块始终是相同的模块,但名称空间是本地的。
  • \n
  • 预编译“配置”只能在第一次使用模块时发生,但您可以随时继续覆盖这些变量。
  • \n
\n

与之前非常相似,只有一个 Derekstrap$h1-font-size变量,并且在编译过程中它会呈现不同的值。模块的功能只是您需要@use在每个想要访问该变量的文件中显式使用 Derekstrap。

\n

我知道这可能需要一些时间来适应,但最终我发现我的代码更有条理。您可能想要建立一个测试项目并进行尝试,直到心智模型更有意义。

\n