Skip to content

主题变量和颜色

本库设计了一套完整的主题配置系统,包含空间大小、颜色和文本样式等配置,全局配置值,组件动态读取。

你可以根据需要进行自定义修改扩展。

主题配置系统可以通过全局配置/局部配置,可以响应式修改主题变量,从而实现动态切换主题。

提示

本库的主题和颜色仅能控制本库组件部分,页面的背景颜色,uniapp标题栏等等部分需要在 App.vue 中通过 css 手动设置。

提示

  • 本库的组件默认单位为 rpx

默认主题说明

默认主题配置文件位于 /components/theme/Theme.ts,该文件定义了默认的主题配置项。

默认主题配置主要包含三个部分: 空间大小配置定义了组件中使用的标准间距尺寸

  1. 颜色配置 (colorConfigs): 颜色配置分为多个分类,每个分类下定义了不同场景使用的颜色,请参考示例页面查看具体颜色值。
  • 默认颜色 (default)
  • 按下颜色 (pressed)
  • 遮罩颜色 (mask)
  • 背景颜色 (background)
  • 文本颜色 (text)
  • 边框颜色 (border)
  1. 文字配置 (textConfigs): 文字配置定义了组件中使用的标准字体尺寸,当使用 Text 组件时,可以快速选择预设好的文字配置。
  2. 主题变量默认设置 (varOverrides):
  • 间距预设 (spaceSize): 用于 Width, Height 等属性的值。
  • 字体大小 (fontSize):字体大小配置定义了组件中使用的标准字体尺寸。

修改主题

你可以在 \src\components\theme\Theme.ts 中直接修改主题配置,但考虑到您后续如果需要更新库版本, 可能会覆盖您的修改,建议通过 configTheme 函数在 App.vue 中修改默认主题配置:

vue
<script setup lang="ts">
import { configTheme } from './components/theme/ThemeDefine';

//修改默认主题颜色
configTheme(true, (theme, darkTheme) => {
  // 修改主要颜色
  theme.colorConfigs.default.primary = '#ff8719';
  theme.colorConfigs.pressed.primary = '#b86212';
  
  // 修改文本颜色
  theme.colorConfigs.text.title = '#333333';
  
  // 修改字体大小
  theme.varOverrides.fontSize.large = 42;
  
  return [theme,darkTheme];
});
</script>

也可创建一个新的主题对象并进行修改,然后实现自定义主题的切换:

vue
<!-- App.vue -->
<script setup lang="ts">
import { cloneTheme, configTheme } from './components/theme/ThemeDefine';
import { DefaultDarkTheme, DefaultTheme } from './components/theme/Theme';

const { currentTheme } = configTheme();

// 克隆并自定义主题
const customTheme = cloneTheme(DefaultTheme);
customTheme.colorConfigs.default.primary = '#ff8719';
customTheme.colorConfigs.pressed.primary = '#b86212';
customTheme.varOverrides.fontSize.large = 42;

// 切换到自定义主题
currentTheme.value = customTheme;
</script>

动态主题切换

组件库支持在运行时动态切换主题,包括亮色主题、暗黑主题和自定义主题。

1. 内置主题切换

组件库默认提供了亮色和暗黑两套主题,当你使用 configTheme 函数时允许你自定义主题,并且附带了自动切换亮色和暗黑主题的功能,第一个参数设置为 true 表示根据系统主题自动切换,默认是 true。

提示,在不同的平台下需要配置 Uniapp 配置才能正确获取系统主题,具体配置请参考 Uniapp 文档

你也可以通过以下方式动态切换:

vue
<!-- App.vue -->
<script setup lang="ts">
import { configTheme } from './components/theme/ThemeDefine';
import { DefaultDarkTheme, DefaultTheme } from './components/theme/Theme';

/**
 * 第一个参数为 true 表示是否根据系统主题自动切换亮色主题/暗黑主题,默认是true
 */
const { currentTheme } = configTheme(true);

// 可以手动切换亮色主题/暗黑主题,需要在 App.vue 中监听事件
onLaunch(() => {
  uni.$on('set-light-theme', () => {
    currentTheme.value = DefaultTheme;
  });
  uni.$on('set-dark-theme', () => {
    currentTheme.value = DefaultDarkTheme;
  });
});
</script>
vue
<!-- 页面中手动触发主题切换 -->
<script setup lang="ts">
const switchToLightTheme = () => {
  uni.$emit('set-light-theme');
};
const switchToDarkTheme = () => {
  uni.$emit('set-dark-theme');
};
</script>

<template>
  <button @click="switchToLightTheme">切换为亮色主题</button>
  <button @click="switchToDarkTheme">切换为暗主题</button>
</template>

2. 自定义主题切换

你可以克隆一个新的主题对象并进行修改,然后实现自定义主题的切换:

vue
<!-- App.vue -->
<script setup lang="ts">
import { cloneTheme, configTheme } from './components/theme/ThemeDefine';
import { DefaultDarkTheme, DefaultTheme } from './components/theme/Theme';

const { currentTheme } = configTheme();

// 克隆并自定义主题
const CustomTheme = cloneTheme(false, (theme) => {
  theme.colorConfigs.default.primary = '#00b66a';
  theme.colorConfigs.pressed.primary = '#00814b';
  theme.colorConfigs.background.primary = '#dcfff0';
  return theme;
});

// 监听自定义主题切换事件
onLaunch(() => {
  uni.$on('set-custom-theme', () => {
    currentTheme.value = CustomTheme;
  });
});
</script>
vue
<!-- 页面中触发自定义主题切换 -->
<script setup lang="ts">
const switchToCustomTheme = () => {
  uni.$emit('set-custom-theme');
};
</script>

<template>
  <button @click="switchToCustomTheme">切换为自定义主题色</button>
</template>

主题变量/颜色

主题变量:每个组件可以设置自己的主题变量,用于从全局或者局部读取配置来自定义组件的样式。

通过主题变量可以方便实现:

  • 修改内置组件的样式或者颜色
  • 批量修改某块组件的样式
  • 动态颜色

本库的组件主题变量都是以组件名称开头的,例如 ProgressTextFontSize 是进度条组件的字体大小变量。关于具体组件的主题变量,请参考各组件文档中的主题变量部分。

如果您在组件中需要使用主题变量,可以使用 propGetThemeVarresolveThemeColorDynamicColor 等函数来获取主题变量:

propGetThemeVar

用于组件中的props获取主题变量作为默认值。

ts
import { propGetThemeVar } from '../theme/ThemeDefine';
const props = withDefaults(defineProps<AvatarProps>(), {
  background: () => propGetThemeVar('AvatarBackground', 'background.imageBox'),
  textColor: () => propGetThemeVar('AvatarTextColor', 'text.content'),
  size: () => propGetThemeVar('AvatarSize', 70),
  radius: () => propGetThemeVar('AvatarRadius', 0),
  round: () => propGetThemeVar('AvatarRound', true),
});

themeContext.xxx

手动获取获取主题变量,颜色,大小。建议包裹在 computed 中使用。

  • resolveThemeSize:获取主题变量,大小。

  • resolveThemeColor:获取主题颜色。

  • getVar:获取主题变量。

    ts
    import { useTheme } from '../theme/ThemeDefine';
    
    const themeContext = useTheme();
    const barColor = computed(() => themeContext.resolveThemeColor('ProgressProgressColor', 'primary'));

DynamicXXX

DynamicXXX 系列函数需要与 useThemeStyle,useThemeStyles 函数配合使用,可以组建动态响应式样式。

  • DynamicColor:获取主题颜色。
  • DynamicVar:获取主题变量。
  • DynamicSize:获取主题变量,大小。
  • DynamicSize2:获取主题变量,大小,适用于 padding, margin 等有两个值的情况。
ts
const themeStyles = themeContext.useThemeStyles({
  progressTextPill: {
    width: DynamicSize('ProgressTextWidth', 80),
    textAlign: DynamicVar('ProgressTextAlign', 'center'),
    padding: DynamicSize2('ProgressTextPaddingVertical', 'ProgressTextPaddingHorizontal', 2, 2),
    borderRadius: DynamicSize('ProgressTextBorderRadius', 20),
    fontSize: DynamicSize('ProgressTextFontSize', 24),
    color: DynamicColor('ProgressTextColor', 'white'),
  },
});

组件级主题变量/颜色

你也可以使用 ProvideVar 组件在局部统一覆盖组件的主题变量,这在自定义组件样式时非常有用,例如下方代码 ProvideVar 下的 GridItem 组件全部使用提供的主题变量:

vue
<template>
  <ProvideVar :vars="{
    GridItemIconSize: 90,
    GridItemBackgroundColor: 'transparent',
  }">
    <Grid :borderGrid="false" :mainAxisCount="4">
      <GridItem title="地图" icon="https://mn.wenlvti.net/uploads/20250326/75fad9e48686483dad24144b62bc5b13.png" touchable @click="navTo('/pages/inhert/map/index')" />
      <GridItem title="文物" icon="https://mn.wenlvti.net/uploads/20250326/bae40c527a2e517f59e2f39835ea6993.png" touchable @click="navTo('/pages/inhert/artifact/list')" />
      <GridItem title="非遗" icon="https://mn.wenlvti.net/uploads/20250326/cb0ebed5768e6cedb51492916678b90e.png" touchable @click="navTo('/pages/inhert/intangible/list')" />
    </Grid>
  </ProvideVar>
</template>

<script setup lang="ts">
import ProvideVar from './components/theme/ProvideVar.vue';
</script>

通过这种方式,你可以仅针对特定组件修改其主题变量,而不影响全局主题配置。

内置CSS

remove-button-style

用于移除微信按钮的默认样式,通常在需要使用按钮调用open-type功能,例如调用微信登录,分享等等时。可以将按钮作为一个容器,内部再放库组件,例如:

vue
<template>
  <button class="remove-button-style" open-type="share">
    <FlexRow :gap="10" align="center" :padding="[0,10]" >
      <Icon icon="share" color="text.content" />
      <Text text="分享" />
    </FlexRow>
  </button>
</template>