You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过Vite插件在Vue中从JS获取Style块内的SCSS变量?

可以实现,以下是具体方案

核心思路

通过开发Vite插件,利用Vite的代码转换钩子拦截Vue单文件组件,提取<style lang="scss">块中的变量,将其转换为JS对象后注入组件的脚本部分,最终让组件能通过自定义方法访问这些变量。

实现步骤与代码示例

1. 安装依赖

需要用到PostCSS解析SCSS语法,若要获取变量引用后的最终计算值,可额外安装Sass:

npm install postcss postcss-scss --save-dev
# 如需处理变量引用,补充安装sass
npm install sass --save-dev

2. 编写Vite插件

创建plugins/vite-plugin-extract-scss-vars.js文件,实现核心逻辑:

import postcss from 'postcss';
import scssSyntax from 'postcss-scss';
// 如需计算变量最终值,引入sass
// import sass from 'sass';

export default function vitePluginExtractScssVars() {
  return {
    name: 'vite-plugin-extract-scss-vars',
    async transform(code, id) {
      // 仅处理Vue单文件组件
      if (!id.endsWith('.vue')) return code;

      // 匹配<style lang="scss">块(兼容带scoped的情况)
      const scssStyleMatch = code.match(/<style lang="scss"(?: scoped)?>(.*?)<\/style>/s);
      if (!scssStyleMatch) return code;

      const scssContent = scssStyleMatch[1];
      const scssVars = {};

      // 方式1:用PostCSS提取原始变量定义(不处理变量引用)
      await postcss([
        {
          postcssPlugin: 'extract-scss-vars',
          Declaration(decl) {
            // 识别SCSS变量(以$开头的声明)
            if (decl.variable) {
              const varName = decl.prop.slice(1);
              scssVars[varName] = decl.value.trim();
            }
          }
        }
      ]).process(scssContent, { syntax: scssSyntax });

      // 方式2:用Sass编译获取计算后的变量值(处理变量引用,如$bar: $foo)
      /*
      sass.compileString(`
        ${scssContent}
        @function collect-vars() {
          $map: ();
          @each $var in variables($global) {
            $map: map-merge($map, ($var: $#{$var}));
          }
          @return $map;
        }
        @debug collect-vars();
      `, {
        functions: {
          'variables($scope)': (scope) => {
            const vars = scope.vars[scope.getValue()];
            return new sass.types.Map(vars.size);
          }
        },
        onWarning(warning) {
          if (warning.message.startsWith('DEBUG:')) {
            const parsedVars = JSON.parse(warning.message.replace('DEBUG: ', ''));
            Object.assign(scssVars, parsedVars);
          }
        }
      });
      */

      // 将变量转换为JS对象字符串
      const varsStr = JSON.stringify(scssVars);
      // 注入getScssVariables方法到<script setup>
      const injectCode = `\nconst __scssVars__ = ${varsStr};\nfunction getScssVariables() { return __scssVars__; }\n`;

      if (code.includes('<script setup>')) {
        // 已有<script setup>,在开头注入代码
        code = code.replace('<script setup>', `<script setup>${injectCode}`);
      } else {
        // 没有<script setup>,添加新的脚本块
        code = `<script setup>${injectCode}</script>\n${code}`;
      }

      return code;
    }
  };
}

3. 在Vite配置中引入插件

修改vite.config.js:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import extractScssVars from './plugins/vite-plugin-extract-scss-vars';

export default defineConfig({
  plugins: [vue(), extractScssVars()]
});

4. 在Vue组件中使用

现在可以直接按示例调用方法:

<script setup>
const variables = getScssVariables();
console.log(variables); // { foo: "30px", bar: "400ms" }
</script>

<template>
  <div :style="{ width: variables.foo, transition: variables.bar }">示例内容</div>
</template>

<style lang="scss">
$foo: 30px;
$bar: 400ms;
</style>

注意事项

  • 若SCSS变量存在嵌套引用(如$bar: $foo),PostCSS仅能提取原始定义,需使用Sass编译方式获取最终计算值。
  • 插件自动兼容带scoped的
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:45:55