H5端(后台管理等):
1.首先使用状态管理,我这里是pinia,vuex也是一样的,新建theme.js
这里关键是使用el.style.setProperty()方法可以修改css变量的值,示例没有做持久化储存,刷新会丢失,可自行添加
import { defineStore } from 'pinia'
export const useThemeStore = defineStore('theme', {
state: () => ({
theme: {
colorPrimary: '#46D52E',
colorPrimaryActive: '#319520',
colorPrimaryLight: '#C7F2C0'
}
}),
actions: {
setAvtiveTheme () {
const el = document.getElementById('app')
if (el) {
el.style.setProperty('--color-primary', this.theme.colorPrimary)
el.style.setProperty('--color-primary-active', this.theme.colorPrimaryActive)
el.style.setProperty('--color-primary-light', this.theme.colorPrimaryLight)
}
},
async getTheme () {
// 只是示例,可以从后端接口获取主题颜色
let res = await api.getTheme()
if (res.success) {
this.theme = res.data
this.setAvtiveTheme()
}
}
}
})
具体使用要看具体需求,如果只是浅色主题和深色主题等更换,只需要在state把主题的配置写好,用开关控制即可。示例:
state: () => ({
theme: {
// 深色主题
dark: {
// 文字颜色
textColor: '#ffffff',
// 背景颜色
backgroundColor: '#000000',
// 边框颜色
borderColor: '#0000004d',
},
// 浅色主题
light: {
textColor: '#000000',
backgroundColor: '#ffffff',
borderColor: '#0000004d',
},
// 当前主题
isDark: false
}
}),
actions: {
setAvtiveTheme (data) {
const el = document.getElementById('app')
if (el) {
el.style.setProperty('--text-color', data.textColor)
el.style.setProperty('--background-color', data.backgroundColor)
el.style.setProperty('--border-color', data.borderColor)
}
},
//修改主题色
changeTheme() {
this.theme.isDark = !this.theme.isDark
if (this.theme.isDark) {
this.setAvtiveTheme(this.theme.dark)
} else {
this.setAvtiveTheme(this.theme.light)
}
},
}
2.在需要使用主题色的页面css使用
.submitBtn{
width: 344px;
background-color: var(--color-primary);
font-weight: 700;
font-size: 16px;
&:active{
background-color: var(--color-primary-active);
}
}
如果是js控制显示主题色的就需要引入仓库使用
<el-switch :style="`--el-switch-on-color: ${themeStore.theme.colorPrimary}`" />
import { useThemeStore } from '@/stores/theme'
const themeStore = useThemeStore()
3.在App.vue入口文件导入并获取颜色
<script setup>
import { RouterView } from 'vue-router'
import { onMounted } from 'vue'
import { useThemeStore } from '@/stores/theme'
const themeStore = useThemeStore()
onMounted(() => {
themeStore.setAvtiveTheme()
})
</script>
<template>
<RouterView />
</template>
注意:此方法仅适用有ducument对象的H5端,后台管理等项目。
uniapp--小程序或app端:
由于uni-app的 js 代码,web 端运行于浏览器中。非 web 端(包含小程序和 App),Android 平台运行在 v8 引擎中,iOS 平台运行在 iOS 自带的 jscore 引擎中,都没有运行在浏览器或 webview 里,因此不支持 window、document、navigator 等浏览器专用对象。
1.这里示例用vuex演示,首先也是新建一个仓库theme.js
const state = {
activeTheme: {
'--color-primary': '#ffbb12',
'--color-primary-active': '#cf9236',
'--color-primary-light': '#C7F2C0',
}
}
const mutations = {
setActiveTheme (state, data) {
state.activeTheme = data
},
}
const actions = {
async getTheme(context,params) {
//模拟从接口获取数据
let res = await api.getTheme()
if (res.success) {
context.commit('setActiveTheme', res.data)
}
},
}
export default {
state,
mutations,
actions
}
2.App.vue 中在小程序启动时引入仓库并获取颜色,此步适用颜色是从后端获取,如果本地存储可不用加:
onLaunch: function() {
// 仓库需要增加方法 getTheme 从接口获取颜色数据
store.dispatch('theme/getTheme')
}
3.在需要用到主题颜色的页面,最外层view绑定仓库的值:
<template>
<view class="test_comtainer" :style="[activeTheme]">
<view class="btn" @click="confirm">确定</view>
</view>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
data () {
return {
}
},
computed: {
...mapState({
activeTheme: store => store.theme.activeTheme
})
},
onLoad () {
},
methods: {
...mapMutations({
setActiveTheme: 'theme/setActiveTheme'
}),
confirm () {
this.setActiveTheme({
'--color-primary': '#46D52E',
'--color-primary-active': '#319520',
'--color-primary-light': '#C7F2C0'
})
}
}
}
</script>
<style lang="scss" scoped>
.test_comtainer {
.btn{
width: 328rpx;
height: 80rpx;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
line-height: 1;
background-color: var(--color-primary);
&:active{
background-color: #cf9236;
}
}
}
</style>
这个方法有个弊端,就是在使用到的页面,都需要绑定一下store里面的数据。比较麻烦。