前面我已經給大家介紹了兩種主題切換的方式,每種方式各有自己的優勢與缺點,例如「scss變數+vuex」方式相容好但不好維護與擴充套件,「scss變數+require」方式好維護但相容不好,還不清楚的可點下面連結直達瞭解一下
uniapp主題切換功能的第一種實現方式(scss變數+vuex)
uniapp主題切換功能的第二種實現方式(scss變數+require)
理解了這些才能更好的理解我接下來給大家總結的。
最後做的這個能相容所有平臺的主題切換效果,大家可以微信掃碼一睹為快,切換功能在」個人中心「那裡(模仿的b站),目前分白天與夜間模式
接下來就給大家介紹一下如何做一個相容好,又好維護的主題切換功能
uniapp應用在做開發的時候,拆分頁面其實就分兩大部分,主體部分+導航欄與tabbar
為什麼要這麼分,因為主體部分的樣式通常是普通css程式碼控制的,而導航欄+tabBar(例如原生的情況)須要通過api去修改。而css與js目前還不能完全互通。
因此要做全平臺相容同樣須要維護主體部分的樣式(純css)與導航欄+tabBar部分的樣式(js),明白了原理,接下來就上程式碼
這樣其實就是之前講過的,上程式碼
$themes: (
// 白天模式
light:(
page: (
background-color: #fff,
color: (
color: #333,
),
block: (
background-color: #333,
color: (
color: #fff,
),
),
),
user-page: (
background-color: #f2f2f2,
color: (
color: #666,
),
block: (
background-color: #999,
color: (
color: #000,
),
),
),
),
// 夜間模式
dark:(
page: (
background-color: #333,
color: (
color: #fff,
),
block: (
background-color: #fff,
color: (
color: #000,
),
),
),
user-page: (
background-color: #1a1a1a,
color: (
color: #fff,
),
block: (
background-color: #FFFFFF,
color: (
color: #000,
),
),
),
)
);
@mixin map-to-class($map, $divider: "-", $select: ".theme", $isRoot: false, $root-select: ".theme") {
$select: if($select== "" and &, &, $select);
@each $k, $v in $map {
$currSelect: if($isRoot, #{$root-select}#{$divider}#{$k}, #{$select}#{$divider}#{$k});
#{$currSelect} {
@if type-of($v) ==map {
@include map-to-class($v, $divider, "", true) {
@content;
}
} @else {
@at-root #{$select} {
#{$k}: $v !important;
}
}
}
}
}
@each $key, $mode in $themes {
@if $key== "light" {
@include map-to-class($mode);
}
}
// 或
@each $key, $mode in $themes {
@if $key== "dark" {
@include map-to-class($mode);
}
}
其實可以迴圈一次性輸出,這個交給你們了。。。
<template>
<view class="tpf-page theme-page">
<text class="theme-color">訂單</text>
<view class="theme-block block flex flex-align-center flex-pack-center">
<text class="theme-color">板塊裡面的文字</text>
</view>
<view class="flex flex-align-center flex-pack-justify change-theme">
<text class="button" @tap="changeTheme('light')">白天模式</text>
<text class="button dark" @tap="changeTheme('dark')">夜間模式</text>
</view>
</view>
</template>
這裡主要通過加theme字首(你自己可以改成想要的)的類theme-page
、theme-color
、theme-block
等等等的方式給內容塊加背景,給字型加顏色等
這樣頁面是不是就很好維護,不同顏色的頁面,你只須要在_theme.scss主題裡面進行新增或修改後,在頁面新增迴應的theme-xxx類即可。
這樣就處理了主體部分的樣式主題切換問題。
因為這部分涉及到原生操作,須要用到api,所以必須是js來維護主題樣式
定義theme.js
// 定義導航欄 與 tabbar 主題色
const themes = {
light:{
navBar:{
backgroundColor:'#FFF',
frontColor:"#000000"
},
tabBar:{
backgroundColor:'#FFF',
color:'#333',
selectedColor:'#0BB640',
borderStyle:'white'
}
},
dark:{
navBar:{
backgroundColor:'#333',
frontColor:"#ffffff"
},
tabBar:{
backgroundColor:'#333',
color:'#fff',
selectedColor:'#0BB640',
borderStyle:'black'
}
}
}
export default themes;
不推薦的原因:::有相容問題!!!
mian.js
//引入主題
import themes from '@/common/theme/theme.js';
....
//全域性掛載
Vue.prototype.$themes = themes;
為什麼使用這兩種,因為他們是目前官方相容所有平臺的,這裡我只介紹Vuex的方式
import Vue from 'vue'
import Vuex from 'vuex'
// 引入主題
import themes from '@/common/theme/theme.js';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
theme:themes[uni.getStorageSync('theme') || 'light']
},
getters: {
},
mutations: {
updateTheme(state,mode = 'light'){
state.theme = themes[mode];
}
}
})
export default store
建立好store之後,就可以在頁面裡面動態設定導航欄與tabBar了,具體大家自己去根據喜好封裝。
onReady(){
//Vuex的方式
// 設定導覽列
uni.setNavigationBarColor(this.$store.state.theme.navBar);
// 設定tabbar
uni.setTabBarStyle(this.$store.state.theme.tabBar);
},
更新就是更改store的狀態,因為他是全域性的,所有頁面都能應用到
this.$store.commit("updateTheme",mode);
// 設定導覽列
uni.setNavigationBarColor(this.$store.state.theme.navBar);
// 設定tabbar
uni.setTabBarStyle(this.$store.state.theme.tabBar);
要想實現全端相容,肯定所有的程式碼都要考慮到相容所有平臺,因為做的時候要就考慮到。
主題切換對於應用來說是一個大工程,原理給大家說了,實現部署還須要大家好好的思考,其中擴充套件性,可維護性等都必須事先考慮的,不然專案肯定做不大。
想看我做的最終成品怎麼樣,可以掃碼看看
有什麼做得不好的,或沒有考慮到位的,歡迎大家留言討論交流,共同學習進步。