uniapp主题切换功能的第一种实现方式(scss变量+vuex)

随着用户端体验的不断提升,很多应用在上线的时候都要求做不同的主题,最基本的就是白天与夜间主题。

就像b站app主题切换,像这样的

uniapp因为能轻松实现多端发布而得到很多开发者的青睐,但每个端的实现也有可能不同,现我把已实现的功能一点点的大家分享给大家,须要的可以参考一下,可扫码看效果。

那么用uniapp如何实现多主题切换呢?

第一种实现方式:CSS变量 + Vuex

第一步:创建store\index.js

创建store,用来保存不同的变量

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
const store = new Vuex.Store({
	state: {
        // 写上默认皮肤的数据
		skin: `
			--nav-bg:#42b983;
			--nav-color:#ffffff;
		`
	},
	getters: {
 
	},
	mutations: {
		// 皮肤更换
		skinPeeler(state,skin = []){
			// 将皮肤配置JSON转为以 ; 分割的字符串(style 值)
			let style = skin.map((item,index)=>{
				return `${item.name}:${item.value}`
			}).join(";");
			state.skin = style;
		}
	}
})
 
export default store

第二步:main.js中引入store

import Vue from 'vue'
import App from './App'

// 引用 Vuex 文件
import store from './store'

Vue.config.productionTip = false

App.mpType = 'app'

const app = new Vue({
	// 使用 Vuex
	store,
    ...App,
})
app.$mount()

第三步:页面使用

利用css变量来更新皮肤

<template>
	<view :style="skin">
		<view class="nav-bar">换肤示例</view>
		<view style="padding: 100rpx;">
			<button type="default" hover-class="none" class="btn">按钮 - 页面中的元素</button>
		</view>
		<view class="card">
			<view style="padding-bottom: 20rpx;">请选择皮肤风格</view>
			<radio-group @change="radioChange">
				<label class="h-flex-x list-item" v-for="(item, index) in items" :key="index">
					<view>
						<radio :value="index.toString()" :checked="index === current" />
					</view>
					<view style="padding-left: 30rpx;">{{item.name}}</view>
				</label>
			</radio-group>
		</view>
	</view>
</template>
 
<script>
	export default {
		data() {
			return {
				items: [
					{
						value: [
							{name:'--nav-bg',value:'#42b983'},
							{name:'--nav-color',value:'#ffffff'}
						],
						name: '默认'
					},
					{
						value: [
							{name:'--nav-bg',value:'#12b7f5'},
							{name:'--nav-color',value:'#333'}
						],
						name: '手机QQ'
					},
					{
						value: [
							{name:'--nav-bg',value:'#ff5500'},
							{name:'--nav-color',value:'#F0E0DC'}
						],
						name: '淘宝'
					},
				],
				current: 0
			}
		},
		computed: {
			skin() {
				return this.$store.state.skin;
			}
		},
		methods: {
			radioChange: function(e) {
				let item = this.items[Number(e.detail.value)].value;
				this.$store.commit("skinPeeler",item);

				// 动态设置导航条颜色
				uni.setNavigationBarColor({
					frontColor:'#ffffff',
					backgroundColor:item[0].value
				});
				
				// 动态设置tabbar样式
				uni.setTabBarStyle({
					backgroundColor:item[0].value,
					color: '#FFF',
					selectedColor: '#FFF',
					borderStyle: 'white'
				});
			}
		}
	}
</script>
 
<style lang="scss">
	page {
		background-color: #fff;
		font-size: 28rpx;
	}
	
	.h-flex-x{
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		align-items: center;
		align-content: center;
	}
	.card{
		background-color: var(--nav-bg);
		color:var(--nav-color);
		padding: 30rpx;
	}
	.list-item{
		height: 90rpx;
		border-top: var(--nav-color) solid 1px;
	}
 
	.nav-bar {
		box-sizing: content-box;
		height: 44px;
		background-color: var(--nav-bg);
		padding-top: var(--status-bar-height);
		color: var(--nav-color);
		line-height: 44px;
		text-align: center;
		font-size: 16px;
	}
 
	.btn {
		background-color: var(--nav-bg) !important;
		color: var(--nav-color) !important;
	}
</style>

最后总结

这就是主题切换的第一种实现

它的好处就是:能实时更换显示主题

但也有不足的地方

不足点:

  • 每个页面样式都维护着主题,耦合度高
  • 一套主题下实现不同页面区别化不方便
  • 增加变量后修改的地方多
  • ...... 更多不足大家补充

还有不懂的地方可以看b站视频:https://www.bilibili.com/video/BV1av4y1K74j/?p=18

posted @ 2023-06-06 15:34  天堂路上  阅读(1227)  评论(0编辑  收藏  举报