3

有时需要设置一些常量两次:在 SASS 和 JS 中(例如为了更好的性能)。有谁知道同步 SASS/SCSS 和 JavaScript 变量以从 JavaScript 或从 SASS 到 JavaScript 访问 SCSS 变量的解决方案?

4

3 回答 3

2

我知道这是大约一年前提出的问题,但我将这个答案作为下一个遇到此问题的可怜草皮的参考。那里可能有更好的解决方案,但这是我唯一能找到/想出的解决方案。

由于 JavaScript 似乎无法.scss直接从任何文件中获取变量,因此我们必须使用正则表达式从文件中获取所需的值。但是因为我们不想让它搜索整个 SASS 文件:

创建一个包含变量的 SASS 文件

我们创建一个新文件 ,_variables.scss供 JavaScript 搜索。假设它看起来像这样:

$menuMobileArrowRotate: 90;
$articleScale: 1.1;

将其导入我们的主 SASS 文件

@import "variables";通过在样式表顶部附近添加将其导入 SASS 。然后我们可以在整个文件中使用这些变量,而不是手动输入值。

将其导入 JavaScript

我要让 JavaScript 读取_variables.scss并将其转换为字符串:

var sassVariables = new XMLHttpRequest();
sassVariables.open("GET", 'http://www.use-absolute-url.com/_variables.scss', false);
sassVariables.send(null);

注意:要支持 IE6 及更早版本,请替换var xmlhttp = new XMLHttpRequest();为:

    if (window.XMLHttpRequest) {
      var sassVariables = new XMLHttpRequest();
    }
    else {
      var sassVariables = new ActiveXObject("Microsoft.XMLHTTP");
    }

(来源)

如果我设置异步。到true,Firebug 向我显示一个声称fileContent不存在的错误。而且由于我的文件只有 4KB,因此我不必担心潜在的性能问题,因为我必须等待它加载。

现在,我要声明我的变量:

var fileContent = sassVariables.responseText, //a string holding the contents of my file
    menuMobileArrowRotate = null,
    articleScale = null;

我在确保文件实际加载之前声明menuMobileArrowRotatearticleScale因为我不希望 JavaScript 给我一个错误并因为它没有加载而搞砸一切。

如果一切正常,我将使用 RegEx 找出每个变量的值。至少我只是浏览一个小文件,而不是搜索整个样式表。

if (sassVariables.status === 200) { //if everything loaded nice and dandy
    menuMobileArrowRotate = fileContent.match(/(?:menuMobileArrowRotate.\s*?)(\d+)/)[1];
    articleScale = data.match(/(?:articleScale.\s*?)((\d+)\.*(\d+)*)/)[1];
}

注意[1]after .match(): RegEx 返回一个数组,我只想要第一个匹配项(在我的情况下,它也是唯一的匹配项)。

对于所有的 JS 放在一起:

if (window.XMLHttpRequest) {
  var sassVariables = new XMLHttpRequest();
}
else {
  var sassVariables = new ActiveXObject("Microsoft.XMLHTTP");
}

sassVariables.open("GET", 'http://mysite.com/sass/_variables.scss', false);
sassVariables.send(null);
var fileContent = sassVariables.responseText,
    menuMobileArrowRotate = null,
    articleScale = null;

if (sassVariables.status === 200) {
    menuMobileArrowRotate = fileContent.match(/(?:menuMobileArrowRotate.\s*?)(\d+)/)[1];
    articleScale = fileContent.match(/(?:articleScale.\s*?)((\d+)\.*(\d+)*)/)[1];
}
console.log(menuMobileArrowRotate); //shows 90
console.log(articleScale); //shows 1.1

我现在可以在这段代码之后在我的 JavaScript 文件中的任何地方使用这些变量。

奖励:媒体查询变量

SASS 不允许您媒体查询中使用变量。但是,我可以使整个 dang 查询成为 mixin,并将其放入_variables.scss

@mixin mediaQuery($point) {
  @if $point == 'mobile' {
    @media only screen and (max-width: 600px) { @content; }
  }
  @if $point == 'somethingElse' {
    @media only screen and (max-width: 1000px) { @content; }
  }
}

style.scss中,我可以拥有:

@include mediaQuery(mobile) {
    //blah
}
@include mediaQuery(somethingElse) {
    //blah
}

然后我可以使用相同的过程来获得所需的值(即 600 和 1000),只是使用不同的 RegEx。

于 2013-04-03T06:11:43.707 回答
0

您可以尝试在 SASS/CSS 注释块中编写 JSON:

/*
    {
        "blue"  : "#{$blue}",
        "green" : "#{$green}"
    }

然后在客户端提取和解析它。

于 2013-09-15T21:51:22.123 回答
0

如果您使用 webpack 和 CSS 模块和 SASS(例如使用 React),您可以使用 :export 伪选择器,如此此处所述

于 2019-10-09T16:21:29.030 回答