前言
一个网站的换肤效果算是一个比较常见的功能,尤其是在后台管理系统中,我们几乎都能看到他的身影,这里给大家提供一个实现思路。
搭建项目
vite+vue3搭建项目这里就不演示了,vite官网里面讲得很清楚。
注:这里使用的css预处理器是sass,使用前要先安装他的依赖:npm i sass
处理项目目录结构
把src目录下的assets和components文件夹删除,新建src/theme/index.scss:
把App.vue里的代码改成:
<template> <div></div>
</template> <script setup>
</script> <style lang="scss" scoped>
</style>
把src/style.css里的代码改成:
body { margin: 0; display: flex; place-items: center; min-width: 320px; min-height: 100vh;
} button { border-radius: 8px; border: 1px solid transparent; padding: 0.6em 1.2em; font-size: 1em; font-weight: 500; font-family: inherit; cursor: pointer; transition: border-color 0.25s; outline: none; //消除默认点击蓝色边框效果
} #app { max-width: 1280px; margin: 0 auto; padding: 2rem; text-align: center;
}
说明: 这里只是实现一个基础的换肤效果,所以文件结构尽量简单化,因此就不引入路由或者其他的项目基础工具。
主要问题
我们在实现一个换肤效果的时候,最重要的一个问题是如何通知系统要使用哪种主题方案,这个其实很好解决,用 document.documentElement.setAttribute 在html标签上进行标记就行。
修改App.vue代码:
<template> <div> <form> 主题切换: <input type="radio" name="gender" v-model="type" value="light" checked @change="onChange"/>light <input type="radio" name="gender" v-model="type" value="dark" @change="onChange" />dark </form> </div>
</template> <script setup> import {ref} from "vue"; const type = ref('light') function onChange(e) { document.documentElement.setAttribute('theme-mode', type.value) }
</script> <style lang="scss" scoped> </style>
很简单的一段代码,用单选框模拟主题切换。当选中不同的主题时,在浏览器控制台Elements里你就会看到,html标签自动添加了一段theme-mode=dark
效果:
里面theme-mode和theme-mode里的值都是可以自定义的。
这里就是通过这样区分不同的主题配色方案的。
抽离css变量
在src/theme/index.scss里抽离css变量
代码:
:root,
:root[theme-mode='light'] {--bg-color: #0052d9;
}:root[theme-mode='dark'] {--bg-color: #2c2c2c;
}
这里有两种主题的配色方案light和dark,实际项目中可以把他抽离到不同的文件下,这里只是提供一个思路,代码比较简单就不做抽离处理。
在src/main.js里引入:
import { createApp } from 'vue'
import './style.css'
import './theme/index.scss'
import App from './App.vue'
使用主题
到这里就可以使用这些抽离出来的css变量了,这里拿一个按钮举例:
<template> <div> <button class="btn">按钮</button> <form> 主题切换: <input type="radio" name="gender" v-model="type" value="light" checked @change="onChange"/>light <input type="radio" name="gender" v-model="type" value="dark" @change="onChange"/>dark </form> </div>
</template> <script setup> import {ref} from "vue"; const type = ref('light') function onChange(e) { document.documentElement.setAttribute('theme-mode', type.value) }
</script> <style lang="scss" scoped> .btn { background-color: var(--bg-color); color: #fff; }
</style>
按钮的样式 background-color: var(–bg-color); 里的 –bg-color 就是上面抽离出来的css变量,效果如下:
源码附件:点此下载