【手把手教学】三种不同的主题换肤的方式!(附源码和demo)

260 阅读3分钟

大家好,我是前端架构师,关注微信公众号【程序员大卫】:

  • 回复 [面试] :免费领取“前端面试大全2025(Vue,React等)”
  • 回复 [架构师] :免费领取“前端精品架构师资料”
  • 回复 [书] :免费领取“前端精品电子书”
  • 回复 [软件] :免费领取“Window和Mac精品安装软件”

背景

做网站的时候,主题换肤是个很常见的需求——比如用户想要白天用浅色模式,晚上自动切换成护眼的暗黑模式;或者电商平台每逢大促需要临时换上节日皮肤。

今天我们就用最简单的代码,聊聊实现主题换肤的三种实用方案。

一、CSS 变量:新手必学的换肤方法

原理:就像给颜色起外号,换个外号就能批量改颜色。比如把「白色」定义成 --bg-color,需要白色的地方都用这个变量,想换颜色时只要改这个变量的值就行。

手把手教学

1. 创建项目(用 Vite 快速搭建)

打开终端输入:

pnpm create vite theme-change --template vue-ts

这样就创建了一个 Vue3 + TS 的项目,目录名是 theme-change

2. 定义颜色变量

新建 src/enums/ThemeEnum.ts 文件:

// 就像给主题贴标签
export enum ThemeEnum {
  LIGHT = "light", // 浅色模式(默认)
  DARK = "dark"    // 暗黑模式
}

3. 写 CSS 变量

新建 src/styles/theme.css

/* 默认浅色模式 */
:root {
  --bg-color: #fff;      /* 背景白 */
  --text-color: #333;    /* 文字黑 */
}

/* 暗黑模式 */
[data-theme="dark"] {
  --bg-color: #242424;   /* 背景黑 */
  --text-color: #fff;    /* 文字白 */
}

再新建 src/styles/page.css

/* 所有用到颜色的地方都用变量 */
body {
  background-color: var(--bg-color);
  color: var(--text-color);
  transition: all 0.3s; /* 加个过渡动画 */
}

4. 让按钮能切换主题

新建 src/hooks/useTheme.ts

import { ref, computed } from "vue";
import { ThemeEnum } from "../enums/ThemeEnum";

// 当前主题(默认浅色)
const theme = ref<ThemeEnum>(ThemeEnum.LIGHT);

// 导出一个开关方法
export const useTheme = () => {
  // 点击按钮时切换主题
  const toggleTheme = () => {
    const newTheme = theme.value === ThemeEnum.LIGHT ? ThemeEnum.DARK : ThemeEnum.LIGHT;
    document.documentElement.setAttribute("data-theme", newTheme); // 修改 HTML 标签的属性
    theme.value = newTheme; // 记住当前主题
  };

  // 判断是不是浅色模式
  const isLightTheme = computed(() => theme.value === ThemeEnum.LIGHT);
  
  return { toggleTheme, isLightTheme };
};

5. 在页面中使用

修改 App.vue

<script setup lang="ts">
import { useTheme } from "./hooks/useTheme";
const { toggleTheme, isLightTheme } = useTheme();
</script>

<template>
  <button @click="toggleTheme">
    {{ isLightTheme ? '🌞 切暗黑' : '🌙 切浅色' }}
  </button>
</template>

效果:点击按钮,页面背景和文字颜色会自动切换,还有过渡动画!

二、CSS 类名控制:处理特殊样式

如果遇到渐变背景、阴影这种不能用变量的情况,可以直接写两套 CSS。

比如卡片样式:

/* 浅色模式卡片 */
.card {
  background: linear-gradient(90deg, #f0f0f0, #ffffff);
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* 暗黑模式卡片 */
[data-theme="dark"] .card {
  background: linear-gradient(90deg, #2d2d2d, #3d3d3d);
  box-shadow: 0 2px 8px rgba(255,255,255,0.1);
}

注意:HTML 标签的 data-theme 属性变化时,所有带 [data-theme] 的样式都会自动生效!

三、切换组件:完全不同的页面结构

如果浅色和暗黑模式的页面结构完全不同,可以用 v-if 切换组件。

<script setup lang="ts">
import LightComponent from "./LightComponent.vue";
import DarkComponent from "./DarkComponent.vue";
import { useTheme } from "../hooks/useTheme";

const { isLightTheme } = useTheme();
</script>

<template>
  <!-- 根据主题显示不同组件 -->
  <LightComponent v-if="isLightTheme" />
  <DarkComponent v-else />
</template>

总结

三种方法各有适用场景:

  1. CSS 变量(推荐新手先用这个)
    优点:改颜色最方便,代码量少
    适用:简单颜色切换

  2. CSS 类名
    优点:能处理渐变、阴影等复杂样式
    适用:需要整体替换样式的场景

  3. 切换组件
    优点:页面结构可以完全不同
    注意:组件太多会影响性能

实际开发小技巧

  • 把主题颜色都定义在 CSS 变量里,方便统一修改
  • localStorage 保存用户选择(代码见源码)
  • 加个加载动画,让切换更流畅

GitHub 源码: github.com/zm8/wechat-…

[在线 Demo] codesandbox.io/p/devbox/rp…

如果本文对你有帮助,欢迎点赞❤️收藏⭐,也欢迎在评论区交流!