2.vueuse-useCssVar实现主题色切换功能

1,161 阅读1分钟

useCssVar实现原理是通过修改css变量的值来自定义主题色,可以单独修改某个dom下的css变量而不影响全局css变量的使用,这就使得可定制主题区域变得非常灵活,除此之外,还可以结合ui框架实现定制主题色,例如element-plus等。具体使用方式请查看官网地址

核心代码如下:

1.hooks定义

// useTheme.ts
import { useCssVar } from '@vueuse/core';
import { useLocalCache } from './useLocalCache';
const { setCache } = useLocalCache();

const themes = {
  defaultTheme: {
    '--sy-primary-bg-color': '#fff',
    '--sy-primary-title-color': '#000',
  },
  customTheme: {
    '--sy-primary-bg-color': '#000',
    '--sy-primary-title-color': '#fff',
  },
};

type Theme = typeof themes;
export type ThemeTypes = keyof Theme;
export type CssVarTypes = keyof Theme['defaultTheme'];

export function useTheme(
  el: HTMLElement | Ref<HTMLElement | null | undefined>,
  type: Ref<ThemeTypes> = ref('defaultTheme')
) {
  const colors: Record<CssVarTypes | string, Ref<any>> = {};

  const switchColor = () => {
    Object.keys(themes[type.value]).forEach((item) => {
      colors[item].value = themes[type.value][item as CssVarTypes];
    });
    setCache('theme', type.value);
  };

  onMounted(() => {
    Object.keys(themes.defaultTheme).forEach((item) => {
      colors[item] = useCssVar(item, el);
    });
    switchColor();
  });

  return {
    switchColor,
  };
}

2.定义css变量(跟useTheme.ts中css变量保持一致)

// styles/theme.scss
:root {
  --sy-primary-bg-color: #fff;
  --sy-primary-title-color: #000;
}

使用示例:

1.在main.ts中引入theme.scss

import './styles/theme.scss';

2.在.vue文件中使用

<template>
    <div class="theme-box fvc my10px" ref="el">
      <div class="text">主题测试区域</div>
    </div>
    <select placeholder="切换主题" v-model="activeTheme" @change="switchTheme">
      <option
        v-for="theme in themeOptions"
        :key="theme.value"
        :value="theme.value"
      >
        {{ theme.label }}
      </option>
    </select>
</template>

<script setup lang="ts">
import { useLocalCache, useTheme, ThemeTypes } from '@/hooks'
const { getCache } = useLocalCache();
const el = ref<HTMLElement>();
const activeTheme = ref<ThemeTypes>(getCache('theme'));
const { switchTheme } = useTheme(el, activeTheme);
</script>

<style lang="scss" scoped>
.theme-box {
  width: 180px;
  height: 40px;
  color: var(--sy-primary-title-color);
  background-color: var(--sy-primary-bg-color);
  border: 1px solid #ccc;
}
</style>
// useLocalCache.ts中theme类型定义代码
import { ThemeTypes } from './useTheme';
const defCache= { 
    theme: 'default' as ThemeTypes,
    // ...
 };
 // getCache、setCache...

代码中用到的useLocalCache的详细代码可以参考之前的文章1.vueuse-useLocalStorage在项目中的使用,也可查看项目源码github