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

文章介绍了如何在Vue应用中利用useCssVar钩子函数实现主题色的切换,通过修改CSS变量值实现定制化主题,并使用useLocalCache存储用户选择的主题,确保页面刷新后主题颜色保持一致。代码示例展示了如何创建和切换不同主题,以及如何结合UI框架如ElementPlus实现更复杂的主题定制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

useCssVar实现原理是通过修改css变量的值来自定义主题色,可以单独修改某个dom下的css变量而不影响全局css变量的使用,这就使得可定制主题区域变得非常灵活。具体使用方式请查看官网地址
最终效果图如下:
默认主题
自定义主题
主要实现代码:

import { CssVarUnion, ThemeUnion } from './type';
import { Themes } from './theme';
import { useLocalCache } from '@/hooks/useLocalCache';

const { setCache } = useLocalCache();
export function useSwitchTheme(
  el: HTMLElement | Ref<any>,
  type: Ref<ThemeUnion> = ref('defaultTheme')
) {
  const colors: Record<CssVarUnion | string, Ref<any>> = {};
  Object.keys(Themes.defaultTheme).forEach((item) => {
    colors[item] = useCssVar(item, el);
  });
  const switchColor = () => {
    Object.keys(Themes[type.value]).forEach((item) => {
      colors[item].value = Themes[type.value][item as CssVarUnion];
    });
    setCache('theme', type.value);
  };
  return {
    switchColor,
  };
}


// type.ts

// a | b | c ---> { a:V; b:V; c:V }
type UnionToObj<K extends string, V = string> = {
  [P in keyof { K: K } as `${K}`]: V;
};

// css变量
export type CssVarUnion = '--sy-primary-title-color' | '--sy-primary-bg-color';
export type TCssVar = Partial<UnionToObj<CssVarUnion>>;

// 主题
export type ThemeUnion = 'defaultTheme' | 'customTheme';
export type TTheme = UnionToObj<ThemeUnion, TCssVar>;

// theme.ts
import { TTheme } from './type';

export const Themes: TTheme = {
  defaultTheme: {
    '--sy-primary-bg-color': '#fff',
    '--sy-primary-title-color': '#000',
  },
  customTheme: {
    '--sy-primary-bg-color': '#000',
    '--sy-primary-title-color': '#fff',
  },
};
// theme.scss(需要将主题色样式文件在main.ts中引入)
// 可以将css变量写在具体的dom下,例如:body, #app等...
:root {
  --sy-primary-bg-color: #fff;
  --sy-primary-title-color: #000;
}

代码中用到的useLocalCache可以参考之前的文章vueuse-useLocalStorage在项目中的使用

// 在useLocalCache增加theme
const defCache: ILocalCache = {
  ...,
  theme: 'defaultTheme',
};
// 获取cache
function getCache(key: 'theme'): ThemeUnion;
...
// 设置cache
function setCache(key: 'theme', value: ThemeUnion): void;
...

使用:

<div class="theme-box" ref="el">
 <div class="text">主题测试区域</div>
</div>
.theme-box {
  width: 180px;
  height: 40px;
  border: 1px solid #ccc;
  background-color: var(--sy-primary-bg-color);
  color: var(--sy-primary-title-color);
}
const el = ref(null);
const activeTheme = ref<ThemeUnion>(getCache('theme'));
const { switchColor } = useSwitchTheme(el, activeTheme);
nextTick(() => {
  switchColor();
});

除此之外,还可以结合ui框架实现定制主题色,例如element-plus等

2023-7-28更新

更新原因同1.vueuse-useLocalStorage在项目中的使用。旧的类型定义太过分散,且不好维护,不利于阅读。本次更新删除了theme.tstype.ts文件,并将useSwitchTheme更名为useTheme。更详细部分请查看 github

// useTheme.ts
import { useLocalCache } from '@/hooks/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,
  };
}

vue中使用示例

const el = ref<HTMLElement>();
const activeTheme = ref<ThemeTypes>(getCache('theme'));
const { switchColor } = useTheme(el, activeTheme);
vueuse相关系列文章

1.vueuse-useLocalStorage在项目中的使用

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

3.vueuse-createFetch实现接口请求及其封装(代替axios)

4.vueuse-useFullscreen优雅的使用全屏及退出全屏

5.vueuse-useDark实现暗黑主题及浅亮主题及Element-Plus暗黑模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值