乐趣区

关于前端:uniapp主题切换功能的方式终结篇全平台兼容

后面我曾经给大家介绍了两种主题切换的形式,每种形式各有本人的劣势与毛病,例如“scss 变量 +vuex”形式兼容好但不好保护与扩大,“scss 变量 +require”形式好保护但兼容不好,还不分明的可点上面链接中转理解一下

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

uniapp 主题切换性能的第二种实现形式(scss 变量 +require)

了解了这些能力更好的了解我接下来给大家总结的。

最初做的这个能兼容所有平台的主题切换成果,大家能够微信扫码一睹为快,切换性能在”集体核心“那里(模拟的 b 站),目前分白天与夜间模式

接下来就给大家介绍一下如何做一个兼容好,又好保护的主题切换性能

解决思路

uniapp 利用在做开发的时候,拆分页面其实就分两大部分,主体局部 + 导航栏与 tabbar

为什么要这么分,因为主体局部的款式通常是一般 css 代码管制的,而导航栏 +tabBar(例如原生的状况)须要通过 api 去批改。而 css 与 js 目前还不能齐全互通。

因而要做全平台兼容同样须要保护主体局部的款式(纯 css)与导航栏 +tabBar 局部的款式(js),明确了原理,接下来就上代码

第一局部:全局“主体局部”主题款式

这样其实就是之前讲过的,上代码

定义 common/css/_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);
    }
}

其实能够循环一次性输入,这个交给你们了。。。

页面应用

<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-pagetheme-colortheme-block 等等等的形式给内容块加背景,给字体加色彩等

这样页面是不是就很好保护,不同色彩的页面,你只须要在_theme.scss 主题外面进行增加或批改后,在页面增加回应的 theme-xxx 类即可。

这样就解决了主体局部的款式主题切换问题。

第二局部:全副“导航栏 +tabBar”主题款式

因为这部分波及到原生操作,须要用到 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; 

第一种应用形式 vue.prototype 的全局挂载(不举荐)

不举荐的起因:::有兼容问题!!!

mian.js

// 引入主题
import themes from '@/common/theme/theme.js';
....
// 全局挂载
Vue.prototype.$themes = themes;

第二种应用形式:Vuex / globalData

为什么应用这两种,因为他们是目前官网兼容所有平台的,这里我只介绍 Vuex 的形式

创立 store.js

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);

最初总结

要想实现全端兼容,必定所有的代码都要思考到兼容所有平台,因为做的时候要就思考到。

主题切换对于利用来说是一个大工程,原理给大家说了,实现部署还须要大家好好的思考,其中扩展性,可维护性等都必须当时思考的,不然我的项目必定做不大。

想看我做的最终成品怎么样,能够扫码看看

有什么做得不好的,或没有思考到位的,欢送大家留言探讨交换,独特学习提高。

退出移动版