在Vue3里使用scss實現(xiàn)簡單的換膚功能
主題色就是網(wǎng)站主色,可以配置到組件庫上面;亮色模式又分為兩種風格:純白風格和背景圖風格,不需要背景圖的話可以刪掉這部分邏輯和相關定義;暗黑模式就是黑底白字。
寫法僅在vue3里有效,vue2或其他框架自行修改寫法
換膚示例

scss文件定義
先在variables.module.scss文件定義并導出初始樣式
注意此文件必須以.module.scss結尾
$main-color: #1677ff;
// while
$while-bg-color: #fafafa;
$while-first-text: #000000e0;
$while-second-text: #000000a6;
$while-third-text: #00000040;
$while-box-bg-color: rgba(255, 255, 255, 0.6);
//dark
$dark-bg-color: #141414;
$dark-first-text: #ffffffd9;
$dark-second-text: #ffffffa6;
$dark-third-text: #ffffff40;
$dark-box-bg-color: rgba(255, 255, 255, 0.05);
:export {
MainColor: $main-color;
//while
WhileBgColor: $while-bg-color;
WhileFirstText: $while-first-text;
WhileSecondText: $while-second-text;
WhileThirdText: $while-third-text;
WhileBoxBgColor: $while-box-bg-color;
//dark
DarkBgColor: $dark-bg-color;
DarkFirstText: $dark-first-text;
DarkSecondText: $dark-second-text;
DarkThirdText: $dark-third-text;
DarkBoxBgColor: $dark-box-bg-color;
}
然后在base.scss里定義不同模式下的css屬性
此文件可以隨意命名
@import "./variables.module";
:root {
--main-width: 1280px;
// 切換背景圖需要的變量
--base-background:url('../bgImgs/bgImg_53.jpeg');
}
// 亮色模式下文字顏色變量
html[data-theme='light']:root{
--first-lv-text: #{$while-first-text};
--second-lv-text: #{$while-second-text};
--third-lv-text: #{$while-third-text};
--box-bg-color: #{$while-box-bg-color};
}
// 暗色模式下的文字顏色變量
html[data-theme='dark']:root{
--first-lv-text: #{$dark-first-text};
--second-lv-text: #{$dark-second-text};
--third-lv-text:#{$dark-third-text};
--box-bg-color: #{$dark-box-bg-color};
}
html[data-theme='dark']{
div,p,span,a,h1,h2,h3,h4,h5,h6,h7,ul,li,button,i{
color: #{$dark-first-text};
}
}
然后在mian.scss里引入這兩個文件并使用css變量
@import './base.scss';
@import "./variables.module";
body {
min-width: var(--main-width);
overflow-x: hidden;
background: var(--base-background) left top no-repeat;
background-size: cover;
transition: all 0.3s ease;
}
修改主題方法定義
然后在
store里定義需要的方法
先定義下ts類型themeTypes.ts(沒有ts的可以忽略)
export interface themeType {
mode: themeMode
bgImg: string
isWhile: boolean
isDark: boolean
mainColor: string
}
export enum themeMode {
light = 'light',
dark = 'dark'
}
再定義個修改css變量的工具類
/** 修改css樣式
* @param {string} property css屬性名
* @param {string} value 要修改的值
*/
export function setCssProperty(property: string, value: string) {
document.documentElement.style.setProperty(property, value);
}
然后在theme.ts里定義
因為亮色模式下分為純白和背景圖,所以需要mode + isWhile和isDark來區(qū)分是亮色模式還是暗黑模式,不需要背景圖的話可以修改這部分邏輯
亮色模式和暗黑模式修改關鍵代碼:window.document.documentElement.setAttribute(‘data-theme’, themeMode.light)
import { computed, reactive, ref } from 'vue'
import { defineStore } from 'pinia'
import { themeMode, type themeType } from './types/themeTypes'
import { setCssProperty } from '@/utils/index'
import variable from '@/assets/styles/variables.module.scss'
export const useThemeStore = defineStore('theme', () => {
/**
* 主題分為兩種模式:亮色和暗黑
* 亮色下又分為兩種風格:純白色風格 和 背景圖風格
* 暗黑模式就是純黑背景模式
* 三種風格不可兼容
* */
const theme = reactive<themeType>({
mode: themeMode.light,
// 修改為你真實的背景圖地址
bgImg: new URL('@/assets/bgImgs/bgImg_53.jpeg', import.meta.url).href, // 僅在mode === light時生效
isWhile: false, // 僅在mode === light時生效
isDark: false,
mainColor: variable.MainColor
})
const setTheme = (mode: themeMode, imgUrl?: string) => {
theme.mode = mode
// theme.isWhile為true表示使用純白模式;確保isDark為false,并且移除背景圖,背景色修改為純白
if (theme.isWhile && mode === themeMode.light) {
theme.isDark = false
window.document.documentElement.setAttribute('data-theme', themeMode.light)
setCssProperty('--base-background', variable.WhileBgColor)
} else if (theme.isDark && mode === themeMode.dark) {
// 暗黑模式,確保isWhile為false,并且移除背景圖,背景色為純黑
theme.isWhile = false
window.document.documentElement.setAttribute('data-theme', themeMode.dark)
setCssProperty('--base-background', variable.DarkBgColor)
} else {
// theme.isWhile和theme.isWhile都為false表示使用背景圖,此時mode必須為light
theme.mode = themeMode.light
theme.isWhile = false
theme.isDark = false
theme.bgImg = imgUrl || theme.bgImg
window.document.documentElement.setAttribute('data-theme', themeMode.light)
setCssProperty('--base-background', `url(${theme.bgImg})`)
}
// 這里把配置存在了本地,有條件的可以存在后臺跟用戶綁定用接口加載
localStorage.setItem('theme', JSON.stringify(theme))
}
//頁面加載時使用此方法加載配置的主體
const loadTheme = () => {
const localTheme = localStorage.getItem('theme')
if (theme) {
Object.assign(theme, JSON.parse(localTheme as string))
setTheme(theme.mode, theme.bgImg)
}
}
return {
theme,
setTheme,
loadTheme
}
})
使用
然后在換膚vue文件里使用這些方法,注:template非完整代碼,僅示例如何調用
<template>
<!--修改主題色我使用的vue3-colorpicker組件 -->
<ColorPicker
is-widget
picker-type="chrome"
shape="square"
v-model:pure-color="theme.mainColor"
format="hex"
@pureColorChange="setMainColor"
/>
<!--修改為純白 暗黑模式-->
<div class="use-style">
<span>純白</span>
<a-switch v-model:checked="theme.isWhile" @change="themeStore.setTheme(themeMode.light)" />
</div>
<div class="use-style">
<span>暗黑</span>
<a-switch v-model:checked="theme.isDark" @change="themeStore.setTheme(themeMode.dark)" />
</div>
<!--選擇皮膚(純白/暗黑模式下,不能選擇)-->
<div class="img-list">
<div
v-for="(img, index) in bgImgList"
:key="index"
class="img-item"
>
<img
:src="img"
:alt="'皮膚' + index"
:style="{ cursor: theme.isWhile || theme.isDark ? 'not-allowed' : 'pointer' }"
loading="lazy"
@click="useImg(img)"
/>
<CheckCircleFilled v-if="theme.bgImg === img" class="selected-icon" />
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
// 把sotre和類型導入進來
import { useThemeStore } from '@/stores/theme';
import { themeMode } from '@/stores/types/appTypes';
import { ColorPicker } from 'vue3-colorpicker';
import 'vue3-colorpicker/style.css';
import { storeToRefs } from 'pinia';
const themeStore = useThemeStore();
const { theme } = storeToRefs(themeStore);
themeStore.loadTheme();
const bgImgList = reactive<string[]>([]);
const imgCurrent = ref(1);
// 獲取圖片列表,我這樣寫是因為放在了本地,根據(jù)你的實際情況修改
function getBgImgList() {
for (let i = 0; i < 100; i++) {
bgImgList.push(new URL(`../../assets/bgImgs/bgImg_${i}.jpeg`, import.meta.url).href);
}
}
onMounted(()=>{
getBgImgList();
})
// 設置主題色,
function setMainColor() {
localStorage.setItem('theme', JSON.stringify(theme.value));
}
function useImg(imgUrl: string) {
if (theme.value.isWhile || theme.value.isDark) return;
themeStore.setTheme(themeMode.light, imgUrl);
}
</script>
如果使用了組件庫,別忘了把主題色配置到組件上
<template>
<a-config-provider
:locale="zhCN"
:theme="{
algorithm: appStore.theme.isDark ? theme.darkAlgorithm : theme.defaultAlgorithm,
token: {
colorPrimary: appStore.theme.mainColor,
},
}"
>
<a-app>
<RouterView />
</a-app>
</a-config-provider>
</template>
<script setup lang="ts">
import zhCN from 'ant-design-vue/es/locale/zh_CN';
import { theme } from 'ant-design-vue';
import { useThemeStore } from '@/stores/theme';
const themeStore = useThemeStore();
</script>
要在不同模式下修改組件庫的樣式,可以創(chuàng)建如antDesign.scss文件來修改
// 主題兼容
html[data-theme='light']{
.ant-layout-sider{
background: rgba(255,255,255,0.4);
}
.ant-layout-header{
background: rgba(255,255,255,0.2);
}
}
html[data-theme='dark']{
.ant-layout-sider{
background: rgba(255,255,255,0.08);
}
.ant-layout-header{
background: rgba(255,255,255,0.05);
}
}
需要其他配置可以自行往關鍵文件里添加
以上就是在Vue3里使用scss實現(xiàn)簡單的換膚功能的詳細內容,更多關于Vue3 scss換膚功能的資料請關注腳本之家其它相關文章!
相關文章
select的change方法傳遞多個參數(shù)的方法詳解
element-ui中的select,checkbox等組件的change方法的回調函數(shù)只有當前選擇的val,如果想再傳入自定義參數(shù)怎么辦,本文給大家分享select的change方法如何傳遞多個參數(shù),感興趣的朋友一起看看吧2024-02-02
vue-drawer-layout實現(xiàn)手勢滑出菜單欄
這篇文章主要為大家詳細介紹了vue-drawer-layout實現(xiàn)手勢滑出菜單欄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-11-11
vue?循環(huán)動態(tài)設置ref并獲取$refs方式
這篇文章主要介紹了vue?循環(huán)動態(tài)設置ref并獲取$refs方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
vuejs element table 表格添加行,修改,單獨刪除行,批量刪除行操作
這篇文章主要介紹了vuejs element table 表格添加行,修改,單獨刪除行,批量刪除行操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
解決VUE項目在IIS部署出現(xiàn):Uncaught SyntaxError: Unexpected&n
這篇文章介紹了解決VUE項目在IIS部署出現(xiàn):Uncaught SyntaxError: Unexpected token < 報錯的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04

