如何导出动态生成的SCSS变量供React使用
问题
我有一个_Variables.scss文件,通过Sass动态生成了所有颜色的CSS变量,现在想在React代码中访问其中的颜色变量,不想直接硬编码颜色值。目前在App.scss里可以通过var(--color-secondary)这类方式使用变量,但尝试用:export导出变量(比如在深色主题配置里写的那段)完全没效果。
附上我的_Variables.scss代码:
$colors-light: ( 'color-primary': #EFEFEF, 'color-primary-variant': #D7D7D7, 'color-primary-variant-light': #AAAAAA, 'color-secondary': #23805C, 'color-secondary-variant': #009687, 'text': #4E4E4E, 'text-alt': #FFFFFF ); $colors-dark: ( 'color-primary': #2F302F, 'color-primary-variant': #4E4E4E, 'color-primary-variant-light': #6E6E6E, 'color-secondary': #48BF91, 'color-secondary-variant': #009687, 'color-header': #484e3d, 'text': #FFFFFF, 'text-alt': #222222, ); /* SASS Functions to create all the CSS variables from the SASS colors above */ @function hexToRGB($hex) { @return red($hex), green($hex), blue($hex); } @mixin generate_colors($colors) { // Colors @each $color, $value in $colors { @if str-slice(#{$value}, 1, 1) == '#' { --#{$color}: #{$value}; } @else { --#{$color}: var(--#{$value}); } } // RGB Colors @each $color, $value in $colors { @if str-slice(#{$value}, 1, 1) == '#' { /* stylelint-disable function-name-case */ --RGB-#{$color}: #{hexToRGB($value)}; /* stylelint-enable function-name-case */ } @else { --RGB_#{$color}: var(--RGB_#{$value}); } } } /* End of SASS functions */ /* Use the SASS functions and the SASS variables to actually create all the CSS color variables; e.g. --color-black: #222222 and --RGB-color-black: 34, 34, 34 */ :root[data-theme='theme-light'] { @include generate_colors($colors-light); --color-true-black: #000000; --RGB-color-true-black: 0, 0, 0; --color-white: #FFFFFF; --RGB-color-white: 255, 255, 255; //--color-orchestrator: #d0ced0; --color-red: #BB0000; --RGB-color-red: 187, 0, 0; --color-red-lighter: #FF2E2E; --color-pink: #E4BFBF; --RGB-color-red-lighter: 255, 46, 46; --color-green: #348D00; --color-blue: #0000CC; --RGB-color-blue: 0, 0, 204; --RGB-color-green: 52, 141, 0; --label-alpha: 0.3; } :root[data-theme='theme-dark'] { @include generate_colors($colors-dark); // this does not work :export { color-primary: var(--color-primary); } --label-alpha: 0.9; }
解决方案
核心问题是:Sass的:export只能导出静态的Sass变量值,无法解析var(--xxx)这类动态CSS变量引用。下面提供两种可行的解决思路:
方法1:直接导出Sass变量
从Sass的颜色映射中提取静态值导出,跳过CSS变量环节:
- 在
_Variables.scss末尾添加全局:export块,按需导出单变量或整套主题:
// 导出浅色主题指定变量 :export { lightPrimary: map-get($colors-light, 'color-primary'); lightSecondary: map-get($colors-light, 'color-secondary'); } // 导出深色主题指定变量 :export { darkPrimary: map-get($colors-dark, 'color-primary'); darkSecondary: map-get($colors-dark, 'color-secondary'); } // 或者导出整套主题映射 :export { themeLight: $colors-light; themeDark: $colors-dark; }
- 在React组件中直接导入使用:
import styles from './_Variables.scss'; // 使用单个变量 console.log(styles.lightPrimary); // #EFEFEF console.log(styles.darkPrimary); // #2F302F // 如果导出的是整套映射,需要先解析(注意:Sass映射会被转为字符串,需自行处理) const lightTheme = JSON.parse(styles.themeLight.replace(/'/g, '"')); console.log(lightTheme['color-primary']); // #EFEFEF
方法2:在React中读取当前生效的CSS变量
如果需要获取动态切换主题后的实际CSS变量值,通过JavaScript读取DOM样式:
- 编写读取CSS变量的工具函数:
const getActiveCssVar = (varName) => { return getComputedStyle(document.documentElement) .getPropertyValue(varName) .trim(); };
- 在组件中使用,支持监听主题变化:
import { useState, useEffect } from 'react'; function ExampleComponent() { const [primaryColor, setPrimaryColor] = useState(''); useEffect(() => { // 初始化获取当前主题的主色 const updateColor = () => setPrimaryColor(getActiveCssVar('--color-primary')); updateColor(); // 监听主题切换事件(假设切换主题时触发自定义事件) document.addEventListener('themeChanged', updateColor); return () => document.removeEventListener('themeChanged', updateColor); }, []); return <div style={{ color: primaryColor }}>动态颜色文本</div>; }
注意事项
- 方法1适合不需要动态切换主题,或需要直接使用静态颜色值的场景;
- 方法2适合主题动态切换,需实时获取当前生效颜色的场景;
- 绝对不要在
:export中使用var(--xxx),Sass无法解析这类动态CSS变量,只能导出静态值。
内容的提问来源于stack exchange,提问作者dmikester1
相关产品推荐
相关产品推荐

