前言
一個網站的換膚效果算是一個比較常見的功能,尤其是在后臺管理系統中,我們幾乎都能看到他的身影,這里給大家提供一個實現思路。
搭建項目
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變量,效果如下: