动态修改主题色(uni-app、H5)

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里面的数据。比较麻烦。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

整把来福

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值