更新记录

1.0.0(2026-01-08) 下载此版本


平台兼容性

uni-app x(4.81)

Chrome Safari Android iOS 鸿蒙 微信小程序

其他

多语言 暗黑模式 宽屏模式
× ×

kux-vite-unocss

一个专为 uni-app x 项目设计的 UnoCSS Vite 插件,支持自动生成、转换和优化 UnoCSS 样式,确保在多端环境中的一致性和兼容性。

✨ 核心特性

  • 🚀 自动扫描:自动扫描项目中的 .uvue 文件,提取 UnoCSS 类名
  • 🔧 智能转换:将现代 CSS 格式转换为 uni-app x 兼容格式
  • 性能优化:内置文件哈希缓存,支持增量构建和热更新
  • 🎨 完整支持:兼容 UnoCSS 所有预设、自定义规则
  • ⚠️ Attributify 限制:由于 uni-app x 框架限制,当前不支持 Attributify 模式
  • 📦 自动输出:生成优化后的 CSS 文件到指定目录
  • 🔍 详细日志:可选的详细日志输出,便于调试和问题排查
  • 🔄 单位转换:自动转换 rem/em/vw/vh/vmin/vmax 等单位为 px/rpx
  • 🎯 颜色格式转换:支持现代 RGB/HSL 格式转换为兼容格式
  • ⚙️ 自定义配置:完全支持 UnoCSS 原生配置和扩展

📦 安装

插件市场kux-vite-unocss

🚀 快速开始

1. 配置 Vite

在你的 vite.config.ts 文件中添加插件:

import { defineConfig } from 'vite'
import unocssForUniAppX from './uni_modules/kux-vite-unocss'

export default defineConfig({
  plugins: [
    unocssForUniAppX({
      // 配置选项(可选)
      outputDir: 'styles/css',
      filename: 'uno.css',
      watch: true,
      cache: true,
      cacheDir: ".hbuilderx/.cache/unocss-uni",
      exclude: ["uni_modules/**", "components/**"],
    })
  ]
})

2. 在页面中使用

.uvue 文件中使用 UnoCSS 类名和主题变量:

<template>
  <view class="p-4 bg-white rounded-lg">
    <text class="text-xl font-bold text-gray-800">Hello UnoCSS</text>
    <view class="mt-4 flex">
      <view class="px-4 py-2 bg-blue-500 text-white rounded">按钮 1</view>
      <view class="px-4 py-2 bg-green-500 text-white rounded">按钮 2</view>
    </view>

    <!-- 使用主题变量 -->
    <view class="mt-4 p-4 rounded" style="background-color: var(--theme-colors-primary);">
      <text class="text-white">主题按钮</text>
    </view>
  </view>
</template>

3. 运行项目

HBuilderX 运行项目, 插件会自动生成 style/css/uno.css 文件,包含所有使用的样式。

⚙️ 配置选项

基础配置

选项 类型 默认值 说明
outputDir string 'style/css' CSS 文件输出目录(相对于项目根目录)
filename string 'uno.css' 生成的 CSS 文件名
watch boolean true 是否监听文件变化并自动重新生成 CSS
cache boolean true 是否启用文件缓存以提升构建速度
cacheDir string '.hbuilderx/.cache/unocss-uni' 缓存目录路径(相对于项目根目录)
include string[] ['pages/**/*.uvue'] 要扫描的文件匹配模式(支持 glob)
exclude string[] ['node_modules/**', 'uni_modules/**', 'components/**'] 排除的文件匹配模式
verbose boolean false 是否输出详细日志,用于调试
strict boolean false 是否启用严格模式(遇到错误时抛出异常)

UnoCSS 配置

选项 类型 默认值 说明
config UserConfig {} UnoCSS 原生配置,用于自定义规则、预设、主题等
defaults UserConfigDefaults undefined UnoCSS 默认配置

UCSS 转换配置

选项 类型 默认值 说明
ucssTransform.verbose boolean false UCSS 转换器的详细日志
ucssTransform.strict boolean false UCSS 转换器的严格模式
ucssTransform.removeInvalid boolean true 是否移除不符合 UCSS 规范的属性
ucssTransform.forbiddenProperties string[] [] 额外需要禁止的 CSS 属性
ucssTransform.unitConvert.enabled boolean true 是否启用单位转换
ucssTransform.unitConvert.baseFontSize number 16 rem/em 转换基准值(1rem = Npx)
ucssTransform.unitConvert.viewportWidth number 750 vw/vmin/vmax 转换基准值(设计稿宽度)
ucssTransform.unitConvert.viewportHeight number 1334 vh/vmin/vmax 转换基准值(设计稿高度)
ucssTransform.unitConvert.customConverters Record<string, (value: number) => string> {} 自定义单位转换器

预设主题配置

选项 类型 默认值 说明
presetTheme.theme Record<string, ThemeColors> {} 多主题配置,支持任意数量的主题(light、dark、ocean、forest 等)
presetTheme.prefix string 'theme' CSS 变量前缀,生成如 --theme-colors-primary
presetTheme.rootSelector string '.app' 默认主题(light)的根元素选择器

🔧 高级配置

1. 使用自定义 UnoCSS 预设

import { defineConfig } from 'vite'
import unocssForUniAppX from './uni_modules/kux-vite-unocss'
import { presetUno } from 'unocss'

export default defineConfig({
  plugins: [
    unocssForUniAppX({
      config: {
        // 自定义预设
        presets: [
          presetUno()
        ],
        // 自定义主题
        theme: {
          colors: {
            primary: '#007AFF',
            secondary: '#5856D6',
            success: '#34C759',
            warning: '#FF9500',
            danger: '#FF3B30'
          },
          spacing: {
            'safe-top': 'env(safe-area-inset-top)',
            'safe-bottom': 'env(safe-area-inset-bottom)'
          }
        },
        // 自定义快捷方式
        shortcuts: {
          'btn': 'px-4 py-2 rounded bg-primary text-white font-medium',
          'card': 'bg-white rounded-lg shadow-sm p-4',
          'flex-center': 'flex items-center justify-center'
        },
        // 自定义规则
        rules: [
          [/^text-shadow-(sm|md|lg)$/, ([, size]) => {
            const shadows = {
              'sm': '0 1px 2px rgba(0,0,0,0.1)',
              'md': '0 2px 4px rgba(0,0,0,0.1)',
              'lg': '0 4px 8px rgba(0,0,0,0.1)'
            };
            return { 'text-shadow': shadows[size] };
          }]
        ],
        // 自定义变体
        variants: [
          (matcher) => {
            if (!matcher.startsWith('dark:')) return matcher;
            return {
              matcher: matcher.slice(5),
              selector: (s) => `[data-theme="dark"] ${s}, .dark ${s}`
            };
          }
        ]
      }
    })
  ]
})

2. 自定义扫描范围

unocssForUniAppX({
  include: [
    'pages/**/*.uvue',
    'components/**/*.vue',
    'src/**/*.uvue',
    'layouts/**/*.vue'
  ],
  exclude: [
    'node_modules/**',
    'uni_modules/**',
    'components/external/**',
    '**/*.test.*'
  ]
})

3. 完整配置示例

import { defineConfig } from 'vite'
import unocssForUniAppX from './uni_modules/kux-vite-unocss'
import { presetUno } from 'unocss'

export default defineConfig({
  plugins: [
    unocssForUniAppX({
      // 基础配置
      outputDir: 'style/css',
      filename: 'uno.css',
      watch: true,
      cache: true,
      cacheDir: '.hbuilderx/.cache/unocss-uni',

      // 扫描范围
      include: ['pages/**/*.uvue'],
      exclude: ['node_modules/**', 'uni_modules/**', 'components/**'],

      // 日志配置
      verbose: false,
      strict: false,

      // 主题配置(明亮/暗黑模式)
      presetTheme: {
        prefix: 'theme',
        rootSelector: '.app',
        theme: {
          light: {
            colors: {
              primary: '#007AFF',
              success: '#34C759',
              gray: {
                50: '#F9FAFB',
                100: '#F3F4F6',
                800: '#1F2937',
                900: '#111827'
              }
            }
          },
          dark: {
            colors: {
              primary: '#0A84FF',
              success: '#30D158',
              gray: {
                50: '#1F2937',
                100: '#374151',
                800: '#F9FAFB',
                900: '#FFFFFF'
              }
            }
          }
        }
      },

      // UnoCSS 配置
      config: {
        presets: [
          presetUno()
        ],
        shortcuts: {
          'btn': 'px-4 py-2 rounded bg-[var(--theme-colors-primary)] text-white'
        }
      },

      // UCSS 转换配置
      ucssTransform: {
        verbose: false,
        strict: false,
        removeInvalid: true,
        unitConvert: {
          enabled: true,
          baseFontSize: 16,
          viewportWidth: 750,
          viewportHeight: 1334
        }
      }
    })
  ]
})

🎨 CSS 主题配置(多主题支持)

插件支持通过 presetTheme 配置自动生成的 CSS 变量,支持任意数量的主题,不限于明亮/暗黑模式。

基础配置

vite.config.ts 中配置主题:

import { defineConfig } from 'vite'
import unocssForUniAppX from './uni_modules/kux-vite-unocss'

export default defineConfig({
  plugins: [
    unocssForUniAppX({
      // 主题配置
      presetTheme: {
        // 主题前缀,生成的 CSS 变量前缀
        // 例如:--theme-colors-primary, --theme-colors-success-6
        prefix: 'theme',

        // 根元素选择器,用于应用默认主题(通常是 light)
        rootSelector: '.app',

        // 主题颜色配置 - 支持任意数量的主题
        theme: {
          // 明亮模式
          light: {
            colors: {
              // 基础颜色
              primary: '#007AFF',
              secondary: '#5856D6',
              success: '#34C759',
              warning: '#FF9500',
              danger: '#FF3B30',

              // 灰度颜色
              gray: {
                50: '#F9FAFB',
                100: '#F3F4F6',
                200: '#E5E7EB',
                300: '#D1D5DB',
                400: '#9CA3AF',
                500: '#6B7280',
                600: '#4B5563',
                700: '#374151',
                800: '#1F2937',
                900: '#111827'
              }
            }
          },

          // 暗黑模式
          dark: {
            colors: {
              // 基础颜色
              primary: '#0A84FF',
              secondary: '#5E5CE6',
              success: '#30D158',
              warning: '#FF9F0A',
              danger: '#FF453A',

              // 灰度颜色
              gray: {
                50: '#1F2937',
                100: '#374151',
                200: '#4B5563',
                300: '#6B7280',
                400: '#9CA3AF',
                500: '#D1D5DB',
                600: '#E5E7EB',
                700: '#F3F4F6',
                800: '#F9FAFB',
                900: '#FFFFFF'
              }
            }
          },

          // 海洋主题(自定义)
          ocean: {
            colors: {
              primary: '#00A8E8',
              secondary: '#007EA7',
              success: '#00F5D4',
              background: '#CAF0F8',
              text: '#03045E'
            }
          },

          // 森林主题(自定义)
          forest: {
            colors: {
              primary: '#34C759',
              secondary: '#30B0C7',
              success: '#4CD964',
              background: '#F8FAF0',
              text: '#1B4332'
            }
          },

          // 日落主题(自定义)
          sunset: {
            colors: {
              primary: '#FF9500',
              secondary: '#FF3B30',
              success: '#FFCC00',
              background: '#FFF9E6',
              text: '#2C1B00'
            }
          }
        }
      }
    })
  ]
})

生成的 CSS 变量

插件会自动为每个主题生成对应的 CSS 变量:

/* 明亮模式变量(使用 rootSelector) */
.app {
  --theme-colors-primary: #007AFF;
  --theme-colors-secondary: #5856D6;
  --theme-colors-success: #34C759;
  --theme-colors-warning: #FF9500;
  --theme-colors-danger: #FF3B30;
  --theme-colors-gray-50: #F9FAFB;
  --theme-colors-gray-100: #F3F4F6;
  /* ... 其他灰度颜色 */
}

/* 暗黑模式变量 */
.dark {
  --theme-colors-primary: #0A84FF;
  --theme-colors-secondary: #5E5CE6;
  --theme-colors-success: #30D158;
  --theme-colors-warning: #FF9F0A;
  --theme-colors-danger: #FF453A;
  --theme-colors-gray-50: #1F2937;
  --theme-colors-gray-100: #374151;
  /* ... 其他灰度颜色 */
}

/* 海洋主题 */
.ocean {
  --theme-colors-primary: #00A8E8;
  --theme-colors-secondary: #007EA7;
  --theme-colors-success: #00F5D4;
  --theme-colors-background: #CAF0F8;
  --theme-colors-text: #03045E;
}

/* 森林主题 */
.forest {
  --theme-colors-primary: #34C759;
  --theme-colors-secondary: '#30B0C7';
  --theme-colors-success: #4CD964;
  --theme-colors-background: #F8FAF0;
  --theme-colors-text: #1B4332;
}

/* 日落主题 */
.sunset {
  --theme-colors-primary: #FF9500;
  --theme-colors-secondary: #FF3B30;
  --theme-colors-success: #FFCC00;
  --theme-colors-background: #FFF9E6;
  --theme-colors-text: #2C1B00';
}

在代码中使用主题变量

1. 在 UnoCSS 配置中使用

export default defineConfig({
  plugins: [
    unocssForUniAppX({
      presetTheme: {
        prefix: 'theme',
        theme: {
          light: {
            colors: {
              primary: '#007AFF',
              success: '#34C759'
            }
          },
          dark: {
            colors: {
              primary: '#0A84FF',
              success: '#30D158'
            }
          }
        }
      },
      config: {
        // 在 UnoCSS 配置中引用主题变量
        shortcuts: {
          'btn-primary': 'bg-[var(--theme-colors-primary)] text-white',
          'text-success': 'text-[var(--theme-colors-success)]'
        }
      }
    })
  ]
})

2. 在模板中使用

<template>
  <view class="app">
    <!-- 使用 CSS 变量 -->
    <view class="card" style="background-color: var(--theme-colors-primary);">
      <text class="text-white">主要按钮</text>
    </view>

    <!-- 使用 UnoCSS 类名 -->
    <view class="bg-[var(--theme-colors-success)] p-4 rounded">
      <text>成功状态</text>
    </view>

    <!-- 暗黑模式适配 -->
    <view class="bg-[var(--theme-colors-gray-800)] dark">
      <text>暗黑模式背景</text>
    </view>
  </view>
</template>

<style>
/* 在样式中直接使用 */
.card {
  border-radius: 8px;
  padding: 16px;
  background-color: var(--theme-colors-primary);
}

.text-primary {
  color: var(--theme-colors-primary);
}
</style>

3. 在 UTS 中动态切换多主题

方法 1:在 store 中定义多主题状态

// store/theme.uts
type ThemeType = 'light' | 'dark' | 'ocean' | 'forest' | 'sunset';

type State = {
  currentTheme: ThemeType;
  isSystemTheme: boolean;
}

export const state = reactive({
  currentTheme: 'light' as ThemeType,
  isSystemTheme: true,
} as State)

// 设置主题
export const setTheme = (theme: ThemeType) => {
  state.currentTheme = theme;
  state.isSystemTheme = false;

  // Web 端通过 class 切换
  // #ifdef WEB
  const rootElement = document.querySelector('.app');
  if (rootElement) {
    // 移除所有主题类
    const themeClasses = ['dark', 'ocean', 'forest', 'sunset'];
    themeClasses.forEach(themeClass => {
      rootElement.classList.remove(themeClass);
    });

    // 添加新主题类(除了 light)
    if (theme !== 'light') {
      rootElement.classList.add(theme);
    }
  }
  // #endif

  // App 端使用系统主题 API
  // #ifdef APP
  if (theme === 'light') {
    uni.setAppTheme({ theme: 'light' });
  } else if (theme === 'dark') {
    uni.setAppTheme({ theme: 'dark' });
  }
  // 注意:自定义主题在 App 端需要结合 class 切换
  // #endif
};

// 检测系统主题
export const detectSystemTheme = () => {
  // #ifdef WEB || MP-WEIXIN
  const info = uni.getAppBaseInfo();
  const isDark = info.hostTheme === 'dark';
  setTheme(isDark ? 'dark' : 'light');
  state.isSystemTheme = true;

  uni.onHostThemeChange((result) => {
    const isDarkMode = result.hostTheme === 'dark';
    setTheme(isDarkMode ? 'dark' : 'light');
  });
  // #endif

  // #ifdef APP
  uni.setAppTheme({ theme: "auto" });
  uni.getSystemInfo({
    success: (res: GetSystemInfoResult) => {
      const appTheme = res.appTheme == "auto" ? res.osTheme! : res.appTheme!;
      setTheme(appTheme == "dark" ? 'dark' : 'light');
      state.isSystemTheme = true;
    }
  });
  uni.onOsThemeChange((res: OsThemeChangeResult) => {
    setTheme(res.osTheme == "dark" ? 'dark' : 'light');
    state.isSystemTheme = true;
  });
  uni.onAppThemeChange((res: AppThemeChangeResult) => {
        setTheme(res.appTheme == "dark" ? 'dark' : 'light');
        state.isSystemTheme = true;
    });
  // #endif
};

// 保存主题到本地存储
export const saveThemePreference = (theme: ThemeType) => {
  uni.setStorageSync('theme-preference', theme);
};

// 加载保存的主题
export const loadThemePreference = (): ThemeType | null => {
  const saved = uni.getStorageSync('theme-preference');
  return saved || null;
};

// 初始化主题
export const initTheme = () => {
  const savedTheme = loadThemePreference();
  if (savedTheme) {
    setTheme(savedTheme);
  } else {
    detectSystemTheme();
  }
};

方法 2:在页面中使用多主题切换器

<template>
  <view class="app" :class="[currentTheme, { 'dark': currentTheme === 'dark' }]">
    <view class="container">
      <!-- 当前主题显示 -->
      <view class="status-bar">
        <text class="text-lg">当前主题:{{ themeLabels[currentTheme] }}</text>
      </view>

      <!-- 主题预览 -->
      <view class="preview-section p-4 rounded-lg">
        <text class="text-xl font-bold mb-4">主题颜色预览</text>
        <view class="color-grid">
          <view class="color-item" v-for="color in primaryColors" :key="color">
            <view :style="{ backgroundColor: color }" class="color-box"></view>
            <text class="text-xs">{{ color }}</text>
          </view>
        </view>
      </view>

      <!-- 主题切换按钮 -->
      <view class="theme-buttons mt-6">
        <view 
          v-for="theme in themes" 
          :key="theme.value"
          class="theme-btn"
          :class="{ 'active': currentTheme === theme.value }"
          @click="selectTheme(theme.value)"
        >
          <view class="theme-icon" :style="{ backgroundColor: theme.color }"></view>
          <text class="theme-name">{{ theme.label }}</text>
        </view>
      </view>

      <!-- 跟随系统开关 -->
      <view class="system-toggle mt-4">
        <text class="mr-2">跟随系统主题</text>
        <switch :checked="isSystemTheme" @change="onSystemToggle" />
      </view>
    </view>
  </view>
</template>

<script setup>
  import { state, setTheme, detectSystemTheme, saveThemePreference } from '@/store/theme'

  type ThemeType = 'light' | 'dark' | 'ocean' | 'forest' | 'sunset';

  // 主题配置
  const themes = [
    { value: 'light' as ThemeType, label: '明亮', color: '#007AFF' },
    { value: 'dark' as ThemeType, label: '暗黑', color: '#0A84FF' },
    { value: 'ocean' as ThemeType, label: '海洋', color: '#00A8E8' },
    { value: 'forest' as ThemeType, label: '森林', color: '#34C759' },
    { value: 'sunset' as ThemeType, label: '日落', color: '#FF9500' }
  ];

  const themeLabels: Record<ThemeType, string> = {
    light: '明亮',
    dark: '暗黑',
    ocean: '海洋',
    forest: '森林',
    sunset: '日落'
  };

  const primaryColors = [
    'var(--theme-colors-primary)',
    'var(--theme-colors-secondary)',
    'var(--theme-colors-success)',
    'var(--theme-colors-warning)',
    'var(--theme-colors-danger)'
  ];

  const currentTheme = ref<ThemeType>(state.currentTheme);
  const isSystemTheme = ref(state.isSystemTheme);

  // 选择主题
  const selectTheme = (theme: ThemeType) => {
    setTheme(theme);
    currentTheme.value = theme;
    isSystemTheme.value = false;
    saveThemePreference(theme);
  };

  // 切换跟随系统
  const onSystemToggle = (e: UniSwitchChangeEvent) => {
    if (e.detail.value) {
      detectSystemTheme();
      isSystemTheme.value = true;
    } else {
      isSystemTheme.value = false;
    }
  };
</script>

<style>
.container {
  padding: 20px;
  min-height: 100vh;
  background-color: var(--theme-colors-background);
  color: var(--theme-colors-text);
}

.status-bar {
  text-align: center;
  padding: 20px 0;
}

.preview-section {
  background-color: #ffffff;
  margin-bottom: 20px;
}

.color-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
}

.color-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.color-box {
  width: 50px;
  height: 50px;
  border-radius: 8px;
  margin-bottom: 8px;
}

.theme-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.theme-btn {
  display: flex;
  align-items: center;
  padding: 12px 20px;
  border-radius: 12px;
  background-color: #f0f0f0;
  border: 2px solid transparent;
}

.theme-btn.active {
  border-color: var(--theme-colors-primary);
  background-color: var(--theme-colors-background);
}

.theme-icon {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  margin-right: 12px;
}

.theme-name {
  font-size: 16px;
  font-weight: 500;
}

.system-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background-color: #ffffff;
  border-radius: 12px;
}
</style>

方法 3:使用 uni-app 的主题 API(App 端)

// #ifdef APP
// 切换到系统定义的明亮/暗黑主题
uni.setAppTheme({
  theme: 'light'  // 'light' | 'dark' | 'auto'
});

// 监听系统主题变化
uni.onOsThemeChange((res) => {
  console.log('系统主题变化:', res.osTheme);
});

// 自定义主题需要结合 class 切换
// 注意:uni-app 只内置了 light/dark/auto 三种主题
// 其他自定义主题(ocean、forest 等)需要通过 class 实现
// #endif

颜色格式要求

  • 十六进制: #007AFF, #FF453A
  • RGB: rgb(0, 122, 255) - 会被转换为十六进制
  • 不支持: 渐变、透明度等复杂格式

实际应用示例

// vite.config.ts
export default defineConfig({
  plugins: [
    unocssForUniAppX({
      presetTheme: {
        prefix: 'theme',
        rootSelector: '.app',
        theme: {
          light: {
            colors: {
              primary: '#007AFF',
              background: '#FFFFFF',
              text: '#000000'
            }
          },
          dark: {
            colors: {
              primary: '#0A84FF',
              background: '#000000',
              text: '#FFFFFF'
            }
          }
        }
      },
      config: {
        shortcuts: {
          'theme-bg': 'bg-[var(--theme-colors-background)]',
          'theme-text': 'text-[var(--theme-colors-text)]',
          'theme-primary': 'bg-[var(--theme-colors-primary)] text-white'
        }
      }
    })
  ]
})
<!-- pages/index/index.uvue -->
<template>
  <view class="app theme-bg theme-text" :class="{ 'dark': isDarkMode }">
    <view class="p-4">
      <view class="theme-primary rounded-lg p-4">
        <text>主题按钮</text>
      </view>

      <view class="mt-4" @click="toggleTheme">
        <text>切换主题</text>
      </view>
    </view>
  </view>
</template>

<script setup>

const isDarkMode = ref(false)

function toggleTheme() {
  isDarkMode.value = !isDarkMode.value
}
</script>

生成的 CSS 文件示例

/* style/css/uno.css */
.app {
  --theme-colors-primary: #007AFF;
  --theme-colors-background: #FFFFFF;
  --theme-colors-text: #000000;
}

.dark {
  --theme-colors-primary: #0A84FF;
  --theme-colors-background: #000000;
  --theme-colors-text: #FFFFFF;
}

.theme-bg {
  background-color: var(--theme-colors-background);
}

.theme-text {
  color: var(--theme-colors-text);
}

.theme-primary {
  background-color: var(--theme-colors-primary);
  color: #FFFFFF;
}

🎨 支持的 CSS 特性

下面仅为部分说明,完整请参考 UCSS 说明

✅ 完全支持的特性

类别 特性 示例 说明
选择器 类选择器 .class-name 标准类名
伪类 :hover, :focus 悬停、聚焦等状态
伪元素 ::before, ::after 伪元素选择器
颜色 RGB/HSL 现代格式 rgb(255 149 0 / 0.5) 转换为 rgba(255, 149, 0, 0.5)
透明度变量 var(--un-bg-opacity) 保留 CSS 变量
单位 rem/em 转 px 1rem16px 基于 baseFontSize
vw/vh 转 rpx 1vw7.5rpx 基于 viewportWidth
vmin/vmax 1vmin7.5rpx 取最小/最大值
绝对单位 1cm, 1in 转换为 px
函数 calc() calc(1rem + 10px) 递归转换内部单位
var() var(--color) 保留不变
env() env(safe-area-inset-top) 保留不变
url() url(/image.png) 保留不变
特殊类 px-{n}rem .px-1rem 保留类名,转换样式
Attributify 属性语法 bg-blue, text-red ⚠️ 不支持 (uni-app x 限制)

❌ 限制或转换的特性

类别 特性 处理方式 说明
布局 float, grid, columns 移除 不支持的布局属性
flex, flex-grow 保留 但值中的单位不转换
过渡 transition-timing-function 移除 不支持的过渡函数
transition-* 保留 但不转换单位
变换 transform 保留 但不转换内部单位
动画 animation 保留 但不转换时间单位
复杂@规则 @keyframes 移除 uni-app x 不支持
@media 移除 建议在代码中处理响应式
@font-face 保留 支持字体定义
CSS 函数 min(), max() 移除 不支持的函数
clamp() 移除 不支持的函数

🔍 CSS 转换示例

1. 颜色格式转换

/* 转换前:现代 RGB 空格分隔格式 */
.bg-primary {
  background-color: rgb(0 122 255 / var(--un-bg-opacity));
}

.text-gray-800 {
  color: rgb(31 41 55 / var(--un-text-opacity));
}

.border-color {
  border-color: rgb(255 149 0 / 0.5);
}

/* 转换后:兼容的 RGBA 格式 */
.bg-primary {
  background-color: rgba(0, 122, 255, var(--un-bg-opacity));
}

.text-gray-800 {
  color: rgba(31, 41, 55, var(--un-text-opacity));
}

.border-color {
  border-color: rgba(255, 149, 0, 0.5);
}

2. 单位转换

/* 转换前:现代单位 */
.rem-unit {
  padding: 1rem;
  margin: 0.5rem 1rem;
}

.vw-unit {
  width: 50vw;
  height: 100vh;
}

.em-unit {
  font-size: 1.5em;
  line-height: 1.2; /* line-height 保持不变 */
}

/* 转换后:兼容单位(默认配置) */
.rem-unit {
  padding: 16px;
  margin: 8px 16px;
}

.vw-unit {
  width: 375rpx;  /* 50 * 750 / 100 */
  height: 1334rpx; /* 100 * 1334 / 100 */
}

.em-unit {
  font-size: 24px;  /* 1.5 * 16 */
  line-height: 1.2; /* 保持不变 */
}

3. px-rem 特殊类处理

/* 转换前:自定义 px-rem 类 */
.px-1rem {
  padding-left: 1rem;
  padding-right: 1rem;
}

.px-2rem {
  margin: 2rem;
}

/* 转换后:保留类名,转换样式 */
.px-1rem {
  padding-left: 16px;
  padding-right: 16px;
}

.px-2rem {
  margin: 32px;
}

4. !important 处理

/* 转换前 */
.btn {
  background-color: rgb(0 122 255 / var(--un-bg-opacity)) !important;
  padding: 1rem !important;
}

/* 转换后 */
.btn {
  background-color: rgba(0, 122, 255, var(--un-bg-opacity)) !important;
  padding: 16px !important;
}

5. calc() 函数转换

/* 转换前 */
.calc-example {
  width: calc(100% - 2rem);
  height: calc(50vh + 10px);
}

/* 转换后 */
.calc-example {
  width: calc(100% - 32px);
  height: calc(667rpx + 10px); /* 50 * 1334 / 100 */
}

6. 完整转换流程示例

/* UnoCSS 生成的原始 CSS */
.btn {
  margin-top: 120px;
  background-color: rgb(0 122 255 / var(--un-bg-opacity)) !important;
  padding-left: 16px;
  padding-right: 16px;
  font-size: 1rem;
}

.safe-area {
  padding-top: env(safe-area-inset-top);
}

.px-1rem {
  padding-left: 1rem;
  padding-right: 1rem;
}

/* 插件转换后的最终输出 */
.btn{margin-top:120px;background-color:rgba(0,122,255,var(--un-bg-opacity))!important;padding-left:16px;padding-right:16px;font-size:16px}.safe-area{padding-top:env(safe-area-inset-top)}.px-1rem{padding-left:16px;padding-right:16px}

📁 输出文件结构

项目根目录/
├── stype/
│   └── css/
│       └── uno.css           # 生成的 CSS 文件(压缩后)
├── pages/
│   └── index/
│       └── index.uvue        # 使用 UnoCSS 的页面
├── .hbuilderx/
│   └── .cache/
│       └── unocss-uni/       # 缓存目录
│           └── cache.json    # 缓存数据
└── vite.config.ts            # Vite 配置文件

生成的 CSS 文件示例

/* style/css/uno.css */
.btn{margin-top:120px;margin-bottom:120px;border-width:0px!important;border-radius:20px;--un-bg-opacity:1!important;background-color:rgba(0,122,255,var(--un-bg-opacity))!important;padding-left:16px;padding-right:16px;padding-top:8px;padding-bottom:8px;--un-text-opacity:1!important;color:rgba(255,255,255,var(--un-text-opacity))!important;font-weight:500;transition-duration:200ms}
.safe-top{padding-top:env(safe-area-inset-top)}
.flex{display:flex}
.bg-warning{--un-bg-opacity:1;background-color:rgba(255,149,0,var(--un-bg-opacity))}
.px-1rem{padding-left:16px;padding-right:16px}

🎯 使用示例

完整项目示例

vite.config.ts

import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import unocssForUniAppX from './uni_modules/kux-vite-unocss'

export default defineConfig({
  plugins: [
    uni(),
    unocssForUniAppX({
      outputDir: 'style/css',
      filename: 'uno.css',
      watch: true,
      cache: true,
      verbose: false,
      config: {
        theme: {
          colors: {
            primary: '#007AFF',
            secondary: '#5856D6',
            success: '#34C759',
            warning: '#FF9500',
            danger: '#FF3B30'
          }
        },
        shortcuts: {
          'btn': 'px-4 py-2 rounded bg-primary text-white font-medium',
          'card': 'bg-white rounded-lg shadow-sm p-4'
        }
      }
    })
  ]
})

pages/index/index.uvue

<template>
  <view class="container">
    <!-- 基础样式 -->
    <view class="p-4 bg-white rounded-lg shadow-md">
      <text class="text-xl font-bold text-gray-800">Hello UnoCSS</text>

      <!-- 按钮组件 -->
      <view class="mt-4 flex gap-2">
        <view class="btn">主要按钮</view>
        <view class="btn bg-secondary">次要按钮</view>
      </view>

      <!-- px-rem 特殊类 -->
      <view class="px-1rem mt-4">
        <text>固定间距的内容</text>
      </view>

      <!-- 安全区域 -->
      <view class="safe-top mt-4">
        <text>安全区域顶部</text>
      </view>
    </view>
  </view>
</template>

<style>
.container {
  min-height: 100vh;
  background-color: #f5f5f5;
}
</style>

生成的 CSS 分析

/* 1. 基础工具类 */
.p-4 { padding: 16px; }
.bg-white { background-color: #ffffff; }
.rounded-lg { border-radius: 8px; }
.shadow-md { box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.text-xl { font-size: 20px; }
.font-bold { font-weight: 700; }
.text-gray-800 { color: rgba(31,41,55,1); }
.mt-4 { margin-top: 16px; }
.flex { display: flex; }
.gap-2 { gap: 8px; }

/* 2. 自定义快捷方式 */
.btn {
  padding: 8px 16px;
  border-radius: 4px;
  background-color: rgba(0,122,255,1);
  color: rgba(255,255,255,1);
  font-weight: 500;
}

/* 3. px-rem 特殊类(保留类名,转换样式) */
.px-1rem {
  padding-left: 16px;
  padding-right: 16px;
}

/* 4. 安全区域 */
.safe-top {
  padding-top: env(safe-area-inset-top);
}

🔧 工作原理

完整处理流程

项目启动
    ↓
1. 文件扫描
    ├─ 读取 include 匹配的文件
    ├─ 排除 exclude 匹配的文件
    └─ 使用 glob 模式匹配
    ↓
2. 类名提取
    ├─ 解析 class="..." 属性
    ├─ 识别 UnoCSS 变体 (hover:, dark:, sm:)
    └─ 去重并存储到全局集合
    ↓
3. 缓存检查
    ├─ 计算文件哈希
    ├─ 检查缓存是否有效(24小时内)
    └─ 缓存命中则跳过提取
    ↓
4. CSS 生成
    ├─ 调用 UnoCSS 生成器
    ├─ 应用所有预设和规则
    └─ 生成原始 CSS
    ↓
5. 颜色转换 (UnoColorConverter)
    ├─ rgb(255 149 0 / var(--un-bg-opacity))
    └─ 转换为 rgba(255, 149, 0, var(--un-bg-opacity))
    ↓
6. UCSS 转换 (UcssTransformer)
    ├─ 移除注释
    ├─ 处理 px-{n}rem 特殊类
    ├─ 解析和验证 CSS 规则
    ├─ 转换颜色格式
    ├─ 移除不支持的 @规则
    ├─ 移除不支持的 CSS 函数
    ├─ 单位转换 (rem/em/vw/vh → px/rpx)
    └─ 压缩 CSS
    ↓
7. 文件输出
    ├─ 确保输出目录存在
    ├─ 写入 CSS 文件
    └─ 保存缓存到磁盘
    ↓
热更新监听(如果启用)

关键组件

1. 类名提取器 (extractClassesFromFile)

  • 匹配 class="..." 属性
  • ⚠️ 不支持 Attributify 语法(uni-app x 限制)
  • 识别 UnoCSS 变体
  • 自动去重

2. 缓存系统

  • 基于文件内容哈希
  • 24小时有效期
  • 支持磁盘持久化
  • 增量构建优化

3. UnoCSS 生成器

  • 使用 @unocss/core
  • 支持所有官方预设
  • 完全自定义配置

4. 颜色转换器 (UnoColorConverter)

  • 转换现代 RGB 空格分隔格式
  • 支持背景、文本、边框颜色
  • 保留 CSS 变量和透明度

5. UCSS 转换器 (UcssTransformer)

  • removeComments: 移除 CSS 注释
  • parseAndTransformRules: 整体解析和转换
    • handlePxRemClasses: 处理 .px-{n}rem
    • transformSingleRule: 转换单个规则
    • transformSelector: 验证选择器
    • transformRulesContent: 处理规则内容
  • normalizeColorCalculations: 颜色格式标准化
  • convertColorFormats: 颜色函数转换
  • removeUnsupportedAtRules: 移除不支持的 @规则
  • removeUnsupportedFunctions: 移除不支持的函数
  • normalizeUnits: 单位转换核心
  • minifyCss: 压缩输出

特殊处理

.px-{n}rem 类

// 输入
.px-1rem { padding: 1rem; }

// 处理流程
1. 匹配正则: /\.px-(\d+(?:\.\d+)?)rem\s*\{([^}]+)\}/
2. 提取 rem 值: 1
3. 转换样式: padding → 16px
4. 保留类名: .px-1rem

// 输出
.px-1rem { padding: 16px; }

单位转换

// 支持的单位转换
'rem'  → 'px'   (1rem = 16px)
'em'   → 'px'   (1em = 16px)
'vw'   → 'rpx'  (1vw = 7.5rpx, 基于 750)
'vh'   → 'rpx'  (1vh = 13.34rpx, 基于 1334)
'vmin' → 'rpx'  (取 vw 和 vh 的最小值)
'vmax' → 'rpx'  (取 vw 和 vh 的最大值)
'cm'   → 'px'   (1cm = 37.795px)
'mm'   → 'px'   (1mm = 3.7795px)
'in'   → 'px'   (1in = 96px)
'pt'   → 'px'   (1pt = 1.333px)
'pc'   → 'px'   (1pc = 16px)

跳过转换的属性

  • line-height: 保留 em 单位
  • word-spacing, letter-spacing: 保留单位
  • z-index, opacity: 纯数字
  • flex, flex-grow, flex-shrink, order: 数字值
  • grid-row, grid-column: 网格行号
  • animation-*, transition-*, transform-*: 保留原始格式

🚨 常见问题与故障排除

Q1: 为什么我的样式没有生成?

可能原因和解决方案:

  1. 文件路径问题

    // 检查 include 配置是否包含你的文件
    include: ['pages/**/*.uvue', 'pages/**/*.vue']
  2. 类名书写错误

    <!-- ❌ 错误 -->
    <view class="px-1rem" />
    
    <!-- ✅ 正确 -->
    <view class="px-1rem" />
  3. 被 exclude 排除

    // 检查 exclude 配置
    exclude: ['node_modules/**', 'uni_modules/**', 'components/**']
    // 如果你的文件在 components 目录下,会被排除
  4. 查看日志

    // 启用详细日志查看问题
    unocssForUniAppX({ verbose: true })

Q2: 样式不更新或缓存问题

解决方案:

# 1. 清除插件缓存
rm -rf .hbuilderx/.cache/unocss-uni

# 2. 清除旧的 CSS 文件
rm -f style/css/uno.css

# 3. 重新构建插件
cd uni_modules/kux-vite-unocss && pnpm build

# 4. 重启开发服务器

或者禁用缓存:

unocssForUniAppX({
  cache: false  // 开发阶段可以禁用
})

Q3: 转换后的 CSS 格式错误

检查点:

  1. 确保使用最新版本

    cd uni_modules/kux-vite-unocss
    git pull  # 或重新下载插件
    pnpm build
  2. 清理所有缓存

    rm -rf .hbuilderx/.cache/unocss-uni
    rm -f style/css/uno.css
  3. 验证配置

    // 确保 ucssTransform 配置正确
    ucssTransform: {
     unitConvert: {
       enabled: true,
       baseFontSize: 16
     }
    }

Q4: 自定义规则不生效

解决方案:

unocssForUniAppX({
  config: {
    rules: [
      [/^custom-([a-z]+)$/, ([, name]) => {
        return { 'custom-property': name };
      }]
    ]
  }
})

注意: 自定义规则生成的 CSS 也会经过 UCSS 转换器处理。

Q5: Attributify 模式不工作

当前不支持:

由于 uni-app x 框架的限制,插件当前不支持 Attributify 模式(即属性语法,如 <view bg-blue text-white>)。

解决方案:

请使用标准的 class 属性语法:

<!-- ✅ 正确(推荐) -->
<view class="bg-blue text-white p-4"></view>

<!-- ❌ 不支持 -->
<view bg-blue text-white p-4></view>

说明:

Attributify 模式虽然在标准 UnoCSS 中可用,但 uni-app x 框架对属性语法的解析存在限制,因此本插件暂不支持此功能。未来如果 uni-app x 框架支持,我们会考虑添加此功能。

Q6: rem 单位转换不正确

检查基准字体大小:

// 默认 1rem = 16px
ucssTransform: {
  unitConvert: {
    baseFontSize: 16  // 如果设计稿是 1rem = 20px,改为 20
  }
}

验证转换:

/* 输入 */
.test { padding: 1rem; }

/* 输出(baseFontSize: 16) */
.test { padding: 16px; }

/* 输出(baseFontSize: 20) */
.test { padding: 20px; }

Q7: vw/vh 转换不符合预期

检查视口配置:

ucssTransform: {
  unitConvert: {
    viewportWidth: 750,   // 设计稿宽度(默认)
    viewportHeight: 1334  // 设计稿高度(默认)
  }
}

转换计算:

/* 输入:设计稿宽度 750px */
.test { width: 50vw; }

/* 输出:50 * 750 / 100 = 375rpx */
.test { width: 375rpx; }

Q8: 构建时报错 "Cannot find module"

解决方案:

# 1. 安装依赖
cd uni_modules/kux-vite-unocss
pnpm install

# 2. 构建插件
pnpm build

# 3. 检查 dist 目录
ls -la dist/
# 应该有:index.mjs, index.d.ts, index.d.mts

Q9: 插件在 HBuilderX 中不工作

检查步骤:

  1. 确保插件在 uni_modules 目录下
  2. 检查 vite.config.ts 路径是否正确
  3. 重启 HBuilderX
  4. 清除 HBuilderX 缓存:工具 → 清除缓存

Q10: 如何验证插件是否正常工作?

测试方法:

  1. 启用详细日志

    unocssForUniAppX({ verbose: true })
  2. 查看生成的 CSS

    cat style/css/uno.css
  3. 检查控制台输出

    • 应该看到 "Found X unique classes"
    • 应该看到 "CSS generated successfully"
  4. 验证转换结果

    # 检查 .px-1rem 是否正确转换
    grep "px-1rem" style/css/uno.css
    # 应该输出:.px-1rem{padding-left:16px;padding-right:16px}

Q11: 性能优化建议

大型项目优化:

unocssForUniAppX({
  // 开发阶段
  watch: true,
  cache: true,
  verbose: false,

  // 生产构建
  // watch: false,
  // cache: true,

  // 限制扫描范围
  include: ['pages/**/*.uvue'],
  exclude: [
    'node_modules/**',
    'uni_modules/**',
    'components/**',
    '**/*.test.*',
    '**/*.spec.*'
  ],

  // 性能配置
  ucssTransform: {
    verbose: false,
    strict: false
  }
})

Q12: 调试技巧

1. 查看中间状态

// 在 ucssTransformer.ts 中临时添加日志
console.log('After handlePxRemClasses:', css);

2. 测试转换器

import { UcssTransformer } from './uni_modules/kux-vite-unocss/src/ucssTransformer';

const transformer = new UcssTransformer({ verbose: true });
const result = transformer.transform('.px-1rem{padding:1rem}');
console.log(result); // 应该输出: .px-1rem{padding:16px}

3. 检查缓存内容

cat .hbuilderx/.cache/unocss-uni/cache.json

Q13: 已知限制

  1. 不支持 CSS Grid:uni-app x 的布局限制
  2. 不支持 @keyframes:需要使用 UTS 实现动画
  3. 不支持媒体查询:建议使用条件编译或 UTS
  4. 不支持伪元素 content:uni-app x 限制
  5. 部分 CSS 函数不支持:min(), max(), clamp() 等

Q14: 获取更多帮助

如果以上方案都无法解决问题:

  1. 查看详细日志

    unocssForUniAppX({ verbose: true, strict: true })
  2. 检查版本兼容性

    # 查看插件版本
    cat uni_modules/kux-vite-unocss/package.json | grep version
  3. 提交 Issue

    • 提供最小复现案例
    • 附上配置文件和错误日志
    • 说明使用的 uni-app x 版本
  4. 查看更新日志

    cat uni_modules/kux-vite-unocss/changelog.md

🔄 完整工作流程

开发阶段

  1. 启动开发服务器

    # HBuilderX 运行项目
    # 或
    npm run dev
  2. 插件初始化

    • 加载缓存(如果启用)
    • 扫描所有匹配文件
    • 提取类名并去重
  3. 首次 CSS 生成

    • 调用 UnoCSS 生成器
    • 转换颜色格式
    • UCSS 转换
    • 写入 style/css/uno.css
  4. 热更新监听

    • 监听文件变化
    • 增量更新类名集合
    • 防抖重新生成 CSS

生产构建

  1. 构建命令

    npm run build
  2. 优化处理

    • 禁用热更新
    • 启用缓存
    • 压缩 CSS
    • 生成最终文件
  3. 部署

    • style/css/uno.css 随项目一起部署
    • 文件已优化,无需额外处理

📊 性能特点

优势

特性 说明 性能影响
缓存机制 文件哈希缓存 ⚡⚡⚡⚡⚡ 极大提升
增量构建 只处理变化的文件 ⚡⚡⚡⚡⚡ 极大提升
防抖更新 500ms 延迟批量处理 ⚡⚡⚡⚡ 提升
类名去重 全局集合自动去重 ⚡⚡⚡ 提升
按需生成 只生成使用的样式 ⚡⚡⚡⚡ 极大提升

优化建议

大型项目(100+ 页面)

unocssForUniAppX({
  cache: true,
  cacheDir: '.hbuilderx/.cache/unocss-uni',
  watch: false,  // 构建时关闭监听
  verbose: false,
  include: ['pages/**/*.uvue'],
  exclude: [
    'node_modules/**',
    'uni_modules/**',
    'components/**',
    '**/*.test.*',
    '**/*.spec.*'
  ]
})

小型项目

unocssForUniAppX({
  cache: true,
  watch: true,
  verbose: true  // 开发阶段开启日志
})

🛠️ 集成指南

与 HBuilderX 集成

插件自动集成,无需额外配置。只需在 vite.config.ts 中添加插件即可。

<!--### 与 CLI 集成 ```bash # 安装插件 npm install kux-vite-unocss # 配置 vite.config.ts # 运行项目 npm run dev ``` -->

与 CI/CD 集成

# 构建命令
npm run build

# 插件会自动:
# 1. 扫描文件
# 2. 生成 CSS
# 3. 输出到 style/css/uno.css
# 4. 保存缓存(可选)

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

开发流程

# 克隆仓库
git clone https://gitcode.com/uvuejs/kux-vite-plugin-unocss
cd kux-vite-plugin-unocss/uni_modules/kux-vite-unocss

# 安装依赖
pnpm install

# 构建插件
pnpm build

# 运行测试
npx tsx test_simple.ts

# 提交代码
git add .
git commit -m "feat: 添加新功能"
git push

📄 许可证

MIT © kux

🔗 相关链接

📝 更新日志

查看 CHANGELOG.md 了解最新更新和修复。

🧪 测试验证

插件提供了完整的功能测试套件,用于验证所有核心功能是否正常工作。

运行测试

# 在插件目录下运行完整测试
cd uni_modules/kux-vite-unocss
npx tsx test-all.mjs

# 仅测试多主题功能
npx tsx test-multitheme.mjs

测试模块

测试套件包含以下 5 个核心功能模块的测试:

1. 颜色格式转换测试 (UnoColorConverter)

测试内容:

  • ✅ 背景颜色转换: rgb(0 122 255 / var(--un-bg-opacity))rgba(0, 122, 255, var(--un-bg-opacity))
  • ✅ 文本颜色转换: rgb(31 41 55 / var(--un-text-opacity))rgba(31, 41, 55, var(--un-text-opacity))
  • ✅ 边框颜色转换: rgb(255 149 0 / var(--un-border-opacity))rgba(255, 149, 0, var(--un-border-opacity))

测试用例数量: 3 个

2. 单位转换测试 (UCSS Transformer)

测试内容:

  • ✅ rem 单位转换: 1rem16px
  • ✅ em 单位转换: 1.5em24px
  • ✅ vw 单位转换: 50vw375rpx (基于 750 设计稿)
  • ✅ vh 单位转换: 100vh1334rpx (基于 1334 设计稿)
  • ✅ vmin 单位转换: 10vmin75rpx
  • ✅ vmax 单位转换: 10vmax133.4rpx
  • ✅ 绝对单位转换: cm, mm, in, pt, pc

测试用例数量: 12 个

3. 多主题功能测试 (PresetTheme)

测试内容:

  • ✅ CSS 变量前缀正确: 使用 -- 前缀 (如 --theme-colors-primary)
  • ✅ 选择器逻辑正确: light 主题使用 rootSelector, 其他主题使用类选择器
  • ✅ 颜色值正确转换: 转换为十六进制格式
  • ✅ 色阶颜色正确生成: 支持 gray-50, gray-500 等色阶

测试用例数量: 6 个

测试配置示例:

{
  prefix: 'theme',
  rootSelector: '.app',
  theme: {
    light: { colors: { primary: '#007AFF' } },
    dark: { colors: { primary: '#0A84FF' } },
    ocean: { colors: { primary: '#00A8E8' } }
  }
}

生成的 CSS 示例:

.app {
  --theme-colors-primary: #007aff;
}

.dark {
  --theme-colors-primary: #0a84ff;
}

.ocean {
  --theme-colors-primary: #00a8e8;
}

4. 类名提取测试 (ClassExtractor)

测试内容:

  • ✅ 基础 class 属性提取: <view class="p-4 bg-white">['p-4', 'bg-white']
  • ✅ 变体语法提取: <view class="hover:bg-blue-500 dark:text-white">
  • ✅ 空 class 处理: 正确处理空字符串
  • ⚠️ Attributify 模式: 由于 uni-app x 框架限制,暂不支持

测试用例数量: 5 个

提取的类名类型:

  • 标准 class 属性: class="p-4 bg-white"
  • UnoCSS 变体: hover:, focus:, dark:, sm:, md:
  • 状态伪类: disabled, checked, first, last

5. 缓存系统测试 (CacheSystem)

测试内容:

  • ✅ 相同内容生成相同哈希
  • ✅ 不同内容生成不同哈希
  • ✅ 大小写敏感
  • ✅ 空格敏感
  • ✅ 空内容哈希处理

测试用例数量: 5 个

缓存特性:

  • 基于文件内容哈希
  • 24 小时缓存有效期
  • 支持磁盘持久化
  • 增量构建优化

测试输出示例

运行 npx tsx test-all.mjs 后,会看到详细的测试报告:

╔══════════════════════════════════════════════════════════╗
║          kux-vite-unocss 功能测试            ║
╚══════════════════════════════════════════════════════════╝

============================================================
📦 模块 1: 颜色格式转换测试 (UnoColorConverter)
============================================================

测试: 背景颜色转换
输入: .bg-primary { background-color: rgb(0 122 255 / var(--un-bg-opacity)); }
期望包含: rgba(0, 122, 255, var(--un-bg-opacity))
实际: .bg-primary { background-color: rgba(0, 122, 255, var(--un-bg-opacity)); }
✅ 通过

测试: 文本颜色转换
...
测试: 边框颜色转换
...

📊 颜色转换测试结果: 3/3 通过

============================================================
📦 模块 2: 单位转换测试 (UCSS Transformer)
============================================================
...

📊 单位转换测试结果: 12/12 通过

============================================================
📦 模块 3: 多主题功能测试 (PresetTheme)
============================================================
...

📊 多主题功能测试结果: 6/6 通过

============================================================
📦 模块 4: 类名提取测试 (ClassExtractor)
============================================================
...

📊 类名提取测试结果: 3/5 通过

============================================================
📦 模块 5: 缓存系统测试 (CacheSystem)
============================================================
...

📊 缓存系统测试结果: 5/5 通过

============================================================
📊 测试结果汇总
============================================================

颜色格式转换:
  ✅ 通过: 3
  ❌ 失败: 0

单位转换:
  ✅ 通过: 12
  ❌ 失败: 0

多主题功能:
  ✅ 通过: 6
  ❌ 失败: 0

类名提取:
  ✅ 通过: 3
  ❌ 失败: 2

缓存系统:
  ✅ 通过: 5
  ❌ 失败: 0

============================================================
总计: 31 个测试
通过: 29 ✅
失败: 2 ❌
成功率: 93.55%
============================================================

测试文件说明

  • test-all.mjs - 完整功能测试套件,包含所有 5 个模块的测试
  • test-multitheme.mjs - 多主题功能专项测试

如何使用测试

1. 开发新功能时:

# 修改代码后运行测试
npx tsx test-all.mjs

# 如果只修改了多主题功能
npx tsx test-multitheme.mjs

2. 测试自定义配置:

修改测试文件中的配置,例如在 test-multitheme.mjs 中修改主题配置:

const presetThemeConfig = {
  prefix: 'mytheme',  // 修改前缀
  rootSelector: '#app',  // 修改选择器
  theme: {
    // 添加你的自定义主题
    custom: {
      colors: {
        primary: '#FF5733',
        secondary: '#C70039'
      }
    }
  }
};

然后运行测试验证配置是否正确。

3. 回归测试:

在发布新版本前,运行完整测试套件确保所有功能正常:

# 清理缓存
rm -rf .hbuilderx/.cache/unocss-uni

# 运行完整测试
npx tsx test-all.mjs

# 构建插件
pnpm build

测试覆盖率

当前测试覆盖的功能:

模块 测试用例 覆盖率
颜色格式转换 3 100%
单位转换 12 100%
多主题功能 6 100%
类名提取 5 60%
缓存系统 5 100%
总计 31 93.55%

常见问题

Q: 测试失败怎么办?

如果测试失败,请检查:

  1. 确保所有依赖已安装: pnpm install
  2. 清理缓存后重试: rm -rf node_modules/.cache
  3. 查看详细错误信息,定位具体问题

Q: 如何添加新的测试用例?

在对应的测试函数中添加新的测试用例对象:

const testCases = [
  {
    name: '新测试用例',
    input: '输入内容',
    expected: '期望结果'
  },
  // 添加更多用例...
];

Q: 测试可以自动化吗?

可以。在 CI/CD 流程中添加测试步骤:

# .github/workflows/test.yml
- name: Run tests
  run: |
    cd uni_modules/kux-vite-unocss
    pnpm install
    npx tsx test-all.mjs

提示:如果在使用过程中遇到问题,请先查看常见问题章节,或启用详细日志进行调试。

文档主体由AI生成

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。