有没有办法将变量从 javascript 导入 sass,反之亦然?

Posted

技术标签:

【中文标题】有没有办法将变量从 javascript 导入 sass,反之亦然?【英文标题】:Is there a way to import variables from javascript to sass or vice versa? 【发布时间】:2012-03-10 09:23:55 【问题描述】:

我正在制作一个依赖于块概念的 CSS 网格系统。所以我有一个基本文件,例如:

$max-columns: 4;
$block-width: 220px;
$block-height: 150px;
$block-margin: 10px;

它被一个mixin使用:

@mixin block ($rows, $columns, $max-columns) 
  display: block;
  float: left;
  margin: $block-margin 0 0 $block-margin;
  box-sizing: border-box;
  width: ($block-width * $columns) - $block-margin;

但我也希望 javascript 能够访问基本文件中的变量。我在想我可以制作一个不可见的 div,并为其赋予 $block-width、$block-height 和 $block-margin 属性并从那里提取值。但是 max-columns 并没有直接映射到任何东西,所以我必须想出一个 hacky 方法来在 div 中呈现它。有没有一种更简洁的方法可以将值从 sass/css 共享到 javascript,反之亦然?

【问题讨论】:

【参考方案1】:

您可以使用服务器端脚本读取 sass 文件,“解析”它并将您需要的值回显到 javascript。

【讨论】:

【参考方案2】:

我认为我的解决方案相当不成熟;但它确实有效......

在我的_base.scss 中,我定义了一些变量:

$menu_bg: rgb(45, 45, 45);
$menu_hover: rgb(0, 0, 0);

menu.scss 我有:

@import "base";

#jquery_vars 
  .menu_bg 
    background-color: $menu_bg;
  
  .menu_hover 
    background-color: $menu_hover;
  

在一个方便的页面模板中:

<span class="is_hidden" id="jquery_vars">
  <span class="is_hidden menu_bg"></span>
  <span class="is_hidden menu_hover"></span>
</span>

最后这允许在附近的 jQuery 脚本中:

var menu_bg = $('#jquery_vars .menu_bg').css("background-color");
var menu_hover = $('#jquery_vars .menu_hover').css("background-color");

这太丑了,我爸爸头上戴着一个包。

jQuery 可以从页面元素中提取任意 CSS 值;但这些元素必须存在。我确实尝试从原始 CSS 中提取其中一些值,而无需在 html 中创建跨度,而 jQuery 提出了undefined。显然,如果将这些变量分配给页面上的“真实”对象,则您实际上并不需要任意的 #jquery_vars 元素。同时,人们可能会忘记.sidebar-left nice-menu li 是用于向 jQuery 提供变量的重要元素。

如果有人有别的东西,那一定比这更干净……

【讨论】:

【参考方案3】:

我想补充一点,现在有几种方法可以使用 JSON 在 Sass 和 JavaScript 之间共享数据。以下是一些详细介绍各种技术的文章的链接:

Making Sass talk to JavaScript with JSON SassyJSON: Talk to the browser Sharing Data Between Sass and JavaScript with JSON

Sass 原生支持 JSON 导入可能只是时间问题。

【讨论】:

【参考方案4】:

另一种方法是使用 gulp-template,这样您就可以为 JavaScript 生成所需的任何结构。

使用 Gulp 和 gulp-template 在 Javascript 和 Sass 之间共享变量 https://youtu.be/UVeUq8gMYco

它是从头开始创建的,因此人们可以从头开始看到它,并且有一个带有最终结果的 git repo:

https://github.com/PocketNinjaCoUk/shared-js-sass-vars-using-gulp/tree/master/dev

你基本上有你的配置对象

保存在 ./dev/config.js

module.exports = 
  defaults: 
    colours: 
      primary: '#fc0'
    ,
    sizes: 
      small: '100px',
      medium: '500px',
      large: '1000px'
    ,
    zIndex: 
      model: 100,
      dropdown: 50,
      header: 10
    
  

那么你就有了 Sass 和 Javascript 的模板,或者更少或任何你想要的。

Sass 下划线模板

保存在 ./dev/templates/sass-config.txt

<% _.each(defaults, function(category, key)  %>
  // Var <%= key %>
  <% _.each(category, function(value, key)  %>
    $<%= key %>: <%= value %>;
  <% ) %>
<% ) %>

Javascript 下划线模板

保存在 ./dev/templates/js-config.txt

namespace.config = ;

<% _.each(defaults, function(monkey, key)  %>
  namespace.config.<%= key %> = 
  <% i = 1 %>
  <% _.each(monkey, function(value, key)  %>
    <% comma = (Object.keys(monkey).length === i) ? '': ',' %>
    <% if(typeof value === 'string') %>
      <%= key %>: '<%= value %>'<%= comma %>
    <% else  %>
      <%= key %> : <%= value %><%= comma %>
    <%  %>
    <% i++ %>
  <% ); %>
  ;
<% ) %>

然后gulp编译一下

var gulp = require('gulp');
var template = require('gulp-template');
var rename = require('gulp-rename');
var removeEmptyLines  = require('gulp-remove-empty-lines');

var sharedVars = require('./dev/config');

gulp.task('compile', function() 
  gulp.src('./dev/templates/sass-config.txt')
    .pipe(template(sharedVars))
    .pipe(rename('_sass-config.scss'))
    .pipe(removeEmptyLines())
    .pipe(gulp.dest('./dev/sass'));

  gulp.src('./dev/templates/js-config.txt')
    .pipe(template(sharedVars))
    .pipe(rename('js-config.js'))
    .pipe(removeEmptyLines())
    .pipe(gulp.dest('./dev/js'));
);

【讨论】:

【参考方案5】:

我建议查看sass-extract,它使用原生 sass 功能将计算的变量值提取到 JSON 中。

此外,如果您使用的是 webpack,sass-extract-loader 将非常容易地像在 const variables = require('sass-extract-loader!./variables.scss'); 中那样要求/导入 sass 文件,并将您的 sass 变量放在一个不错的 JSON 对象中。

由于它还支持@import 语句,您仍然可以将变量分隔在不同的文件中,无需添加额外的预处理或使用变量分隔 json 文件。

正如其他答案中提到的,有许多替代方法可以实现这一点,您选择哪一种取决于您的用例和环境。

免责声明,我是上述两个库的作者。

【讨论】:

【参考方案6】:

如果你使用 webpack,你可以使用 sass-loader 来导出变量,例如:

$animation-length-ms: $animation-length + 0ms;

:export 
  animationMillis: $animation-length-ms;

然后像这样导入它们

import styles from '../styles/animation.scss'    
const millis = parseInt(styles.animationMillis)

https://blog.bluematador.com/posts/how-to-share-variables-between-js-and-sass/

【讨论】:

这个!这应该是公认的答案。我建议在导出时像:export animationMillis: strip-unit($animation-length-ms); 和strip-unit 一样剥离单元,这样我们就可以直接将变量用作数字而无需解析字符串。 完美解决方案! 在我运行 webpack@5.45.1sass-loader@12.1.0node-sass@6.0.1 的环境中不起作用。变量styles 记录为undefined,因此我无法访问:export 中声明的变量。有什么想法吗?【参考方案7】:

这可以使用gulp-sass-vars-to-js 来完成。它从您的 .scss 文件生成一个 .js 文件。 .js 文件包含在 .scss 文件中声明的所有变量。然后你可以将这个生成的 js 'require' 到你的 .js 中

【讨论】:

【参考方案8】:

sass-ffi 应该可以解决问题,但方式相反(从 JS 到 SASS/SCSS)。它将定义一个名为ffi-require 的函数,它允许您从SASS 中require .js 文件:

config.js:

module.exports = 
     maxColumns: 4,
;

style.scss:

$max-columns: ffi-require('./config', 'maxColumns');

适用于 sass-loader (webpack) 和 node-sass

【讨论】:

以上是关于有没有办法将变量从 javascript 导入 sass,反之亦然?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法用javascript从字符串创建一个函数?

可以将 JavaScript 变量保存为文件吗? [复制]

nodeJS + Swig模板将变量传递给javascript

有没有办法将 pmml 文件导入 python?

从javascript访问CSS变量[重复]

有没有办法使用 foreach 或 unwind 将 csv 导入 Neo4j?