给自己打个广告,我的前端面试、娱乐小程序  —— 工具人的工具箱

一、原理

换肤能够实现的终极密码是——CSS变量,可以为每个主题设定一组CSS变量,包含这个主题的所有颜色、字体等信息,当需要切换主题时,只需要更改使用的CSS变量组即可。

  1. 声明变量。在 :root 伪类中声明 CSS 变量,这样就能在全局范围内使用变量:

:root {
  --main-color: #06c;
}
  1. 使用变量。在你的 CSS 中,使用 var() 函数来使用 CSS 变量:

.header {
  background-color: var(--main-color);
}

二、demo实现

下面我们用Vue3+Element-plus为例,来实现一波高亮模式+暗黑模式两个主题色,可参考element-plus暗黑模式介绍。

2.1 引入主题色样式

在src/styles下面新建theme.scss,把默认暗黑主题色引入进来,并可以在其里面覆盖原有变量或新增一些变量

// theme.scss
/** element内置暗黑主题 */
@use 'element-plus/theme-chalk/src/dark/css-vars.scss' as *;

// 可以进行一些样式的覆盖
html {
    --v-bg-color: #cfcccc; // 新增
}

html.dark {
    --v-bg-color: #141414; // 新增
  	--el-color-primary: #409eff; // 覆盖
}

在main.ts中引入默认主题色和暗黑模式主题色

// main.ts 文件
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
// element默认主题
import 'element-plus/dist/index.css'
import './style.css';
// 公共样式,包含自定义暗黑模式,element重置样式
import './styles/index.scss';
import App from './App.vue';

const app = createApp(App);
app.use(ElementPlus);
app.mount('#app')

此时在浏览器控制台就可以看到很多变量

0dc3964c8693e060e97af1ac782a814f.png

2.2 主题色切换能力

主题切换能力其核心关注点为:

  1. 利用provide注入当前主题及修改主题的方法,然后在组件中通过inject获取主题及主题修改方法;

  2. 利用localStorage持久化存储主题;

  3. 改变html的class属性,进而决定使用哪一套主题;

<script setup lang="ts">
import {provide, ref, onMounted} from 'vue';
import SwitchDark from './components/SwitchDark.vue';

// 改变属性,确定使用哪一套样式
const addThemeAttribute = (theme: string) => {
  const html = document.documentElement;
  html.setAttribute('class', theme);
}

const theme = ref(localStorage.getItem('myTheme') || 'light');

onMounted(() => {
  addThemeAttribute(theme.value);
});

const setTheme = (newTheme: string) => {
  // 改变主题
  theme.value = newTheme;

  addThemeAttribute(newTheme);

  localStorage.setItem('myTheme', newTheme);
};

provide('theme', {
  theme,
  setTheme
});

</script>

<template>
  <SwitchDark />
  <div class="bg">
    我是内容
  </div>
</template>

<style scoped>
.bg {
  background-color: var(--v-bg-color);
  width: 200px;
  height: 200px;
}
</style>

2.3 切换按钮

切换主题色肯定需要一个按钮,下面利用el-switch实现了一个简单的切换按钮,并利用setTheme来切换对应的主题。

4ef717812d7f0fa7def75d81c0f52a4b.png
<template>
    <el-switch
        v-model="isDark"
        inline-prompt	
        @change="changeTheme"
        :active-icon="Sunny"
        :inactive-icon="Moon"
        size="large"
    />
</template>

<script setup lang="ts">
import {inject, Ref, computed} from 'vue';
import {Sunny, Moon} from '@element-plus/icons-vue';

const {theme, setTheme} = inject<{theme: Ref<string>, setTheme: (newTheme: string) => void}>('theme') || {};
const isDark = computed(() => theme?.value === 'dark');

const changeTheme = () => {
    console.log(theme?.value)
    if (theme?.value === 'light') {
        setTheme?.('dark');
    } else {
        setTheme?.('light');
    }
};
</script>

<style scoped>
</style>
GitHub 加速计划 / vu / vue
82
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
9e887079 [skip ci] 2 个月前
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐