在上一篇 「uniapp主題切換功能的第一種實現方式(scss變數+vuex)」 中介紹了第一種如何切換主題,但我們總結出一些不好的地方,例如擴充套件性不強,維護起來也困難等等,那麼接下我再給大家介紹另外一種切換主題的方法「scss變數+require」的方式
在介紹如何使用前,先看下最後的效果,以便大家能更好的理解,下面是效果圖:
除了圖上的這個頁面切換了外,整體專案都有主題色的切換,具體效果可掃碼自行檢視。
接下來詳細介紹下第二種實現方式
定義兩套主題色(多套再自己加)theme-dark.scss、theme-light.scss,每套主題色維護著自己的顏色,通過require動態引入scss的形式引入當前主題,從而達到切換主題的目的
建立白天與夜晚模式
common/theme/theme-dark.scss
/* 切換主題主要切換的是 整體背景色、區塊背景色、文字顏色等 */
// 頁面主題
.theme-page{
background-color: #333 !important;
// 文字顏色
.theme-color{
color: #FFF !important;
}
// 區塊主題色
.theme-block{
background-color: #FFFFFF !important;
.theme-color{
color: #000 !important;
}
}
}
// 如果想單獨給個人中心設定一個主題色
.theme-user-page{
background-color: #1a1a1a !important;
// 文字顏色
.theme-color{
color: #FFF !important;
}
// 區塊主題色
.theme-block{
background-color: #FFFFFF !important;
.theme-color{
color: #000 !important;
}
}
}
common/theme/theme-light.scss
/* 切換主題主要切換的是 整體背景色、區塊背景色、文字顏色等 */
// 頁面主題
.theme-page{
background-color: #FFF !important;
// 文字顏色
.theme-color{
color: #333 !important;
}
// 區塊主題色
.theme-block{
background-color: #999 !important;
.theme-color{
color: #333 !important;
}
}
}
// 如果想單獨給個人中心設定一個主題色
.theme-user-page{
background-color: #F2F2F2;
// 文字顏色
.theme-color{
color: #666 !important;
}
// 區塊主題色
.theme-block{
background-color: #999 !important;
.theme-color{
color: #000 !important;
}
}
}
東西多了的情況,例如有5套主題色,分開不是很好維護,所以
可以考慮把顏色值獨立出去
定義_theme.scss
$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);
}
}
大家可以用sass編輯器看一下最終的樣式是什麼樣的
在App.vue裡面通過require動態引入主題,當前每次切換主題的時候要把當前主題資料進行儲存。
onLaunch: function() {
let theme = uni.getStorageSync('theme') || 'light';
// import `@/common/theme/theme-${mode}.scss`; //記住不能import哦
require(`@/common/theme/theme-${theme}.scss`);
},
// ......
這樣就實現了動態引入
以後只須要維護_theme.scss即可
測試程式碼:
<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>
<script>
export default{
data(){
return {
}
},
methods:{
changeTheme(mode){
uni.setStorageSync('theme',mode);
setTimeout(()=>{
location.reload();
},200);
}
},
onReady() {
let theme = uni.getStorageSync('theme') || 'dark';
if(theme == 'dark'){
// 動態設定導覽列顏色
uni.setNavigationBarColor({
frontColor:'#ffffff',
backgroundColor:'#333333'
});
// 動態設定tabbar樣式
uni.setTabBarStyle({
backgroundColor:'#333333',
color: '#FFF',
selectedColor: '#0BB640',
borderStyle: 'white'
});
}else{
// 動態設定導覽列顏色
uni.setNavigationBarColor({
frontColor:'#000000',
backgroundColor:'#FFFFFF'
});
// 動態設定tabbar樣式
uni.setTabBarStyle({
backgroundColor:'#FFFFFF',
color: '#333',
selectedColor: '#0BB640',
borderStyle: 'black'
});
}
}
}
</script>
<style lang="scss" scoped>
.block{
width: 710rpx;
height: 300rpx;
margin: 20rpx 0;
}
.change-theme{
width: 400rpx;
}
.button{
background-color:#FFF;
color: #000;
padding: 20rpx;
}
.dark{
background-color: #000;
color: #FFF;
}
</style>
在這裡導航欄與tabbar都是通過手動設定的,因為必須是js操作,所以樣式不能去讀css,為了方便,我們也可以定義一個theme.js專門來維護導航欄與tabar樣式
theme.js定義主題案例程式碼:
const themes = {
light:{
navBar:{
bgColor:'#000',
color:'#FFF'
},
tabBar:{
bgColor:'#000',
color:'#FFF',
borderStyle:'black'
}
},
dark:{
navBar:{
bgColor:'#FFF',
color:'#000'
},
tabBar:{
bgColor:'#f2f2f2',
color:'#333',
borderStyle:'white'
}
}
}
let mode = 'dark'
export default themes[mode];
頁面就可以通過引入這個js,通過當前主題引入相關的設定即可。這樣方便統一維護與管理 。
scss變數+require的方式明顯比第一種要好,減少了頁面與主題的耦合度,維護起來也方便
但出於一些效能上的問題(官方回答),在某些平臺或版本已經取消了require動態引入樣式的功能,因此這個是有相容問題的。
這就是我給大家介紹的第二種unippa主題切換的方式,有問題歡迎大家留言交流。https://www.cnblogs.com/top8/p/17460706.html