uniapp主題切換功能的第一種實現方式(scss變數+vuex)

2023-06-06 18:01:15

隨著使用者端體驗的不斷提升,很多應用在上線的時候都要求做不同的主題,最基本的就是白天與夜間主題。

就像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