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-page、theme-color、theme-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);
最后总结
要想实现全端兼容,肯定所有的代码都要考虑到兼容所有平台,因为做的时候要就考虑到。
主题切换对于应用来说是一个大工程,原理给大家说了,实现部署还须要大家好好的思考,其中扩展性,可维护性等都必须事先考虑的,不然项目肯定做不大。
想看我做的最终成品怎么样,可以扫码看看

有什么做得不好的,或没有考虑到位的,欢迎大家留言讨论交流,共同学习进步。
uniapp主题切换功能的方式终结篇(全平台兼容)的更多相关文章
- 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- iOS开发之App主题切换完整解决方案(Swift版)
本篇博客就来介绍一下iOS App中主题切换的常规做法,当然本篇博客中只是提到了一种主题切换的方法,当然还有其他方法,在此就不做过多赘述了.本篇博客中所涉及的Demo完全使用Swift3.0编写完成, ...
- Android主题切换—夜间/白天模式探究
现在市面上众多阅读类App都提供了两种主题:白天or夜间. 上述两幅图片,正是两款App的夜间模式效果,所以,依据这个功能,来看看切换主题到底是怎么实现的(当然现在github有好多PluginThe ...
- 基于 Flutter 以两种方式实现App主题切换
概述 App主题切换已经成为了一种流行的用户体验,丰富了应用整体UI视觉效果.例如,白天夜间模式切换.实现该功能的思想其实不难,就是将涉及主题的资源文件进行全局替换更新.说到这里,我想你肯定能联想到一 ...
- CI框架主题切换的功能
CI框架主题切换的功能 本人接触到这个框架不就,属于菜鸟 , 公司现在用CI框架做项目 ,老大要做一个主题切换的功能,说明功能的要求我的脑子里瞬间有几个想法. 脑子里最简单的就是设置全局变量 如 : ...
- jQuery实现无刷新切换主题皮肤功能
主题皮肤切换功能在很多网站和系统中应用,用户可以根据此功能设置自己喜欢的主题颜色风格,增强了用户体验.本文将围绕如何使用jQuery实现点击无刷新切换主题皮肤功能. 查看演示DEMO:https:// ...
- JS组件系列——表格组件神器:bootstrap table(三:终结篇,最后的干货福利)
前言:前面介绍了两篇关于bootstrap table的基础用法,这章我们继续来看看它比较常用的一些功能,来个终结篇吧,毛爷爷告诉我们做事要有始有终~~bootstrap table这东西要想所有功能 ...
- JavaScript中的正则表达式(终结篇)
JavaScript中的正则表达式(终结篇) 在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的.这篇博文我们将通过下面几个部分来了解正则表达式在JavaScri ...
- WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享
系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...
- windows phone主题切换(换肤)
之前项目做了个主题切换的功能,最后客户没来得及出第二套界面给放弃了,默哀中... 为了不让它就这样流产了,就放博客共享吧. 首先说明下原理:这个切换是通过重写资源字典里指定的样式,在运行的过程中加载指 ...
随机推荐
- 【接口测试】Postman(二)-Postman Echo
Postman Echo Postman Echo为用户提供API调用的示例服务.简而言之,就是官方提供的一个API帮助文档.初学者可以通过它很快的掌握Postman工具.我们下面将一一介绍他们. ...
- 自己动手从零写桌面操作系统GrapeOS系列教程——24.加载并运行loader
学习操作系统原理最好的方法是自己写一个简单的操作系统. 之前我们在电脑的启动过程中介绍过boot程序的主要任务就是加载并运行loader程序,本讲我们就来实现. 本讲代码文件共2个: boot.asm ...
- MySQL--索引的数据结构
1.为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页面,便可以快速定位到需要的文章,mysql中也是一样的道理,进行数据查找时, ...
- Kubernetes(k8s)二进制高可用安装脚本
好久没写公众号了,昨天新写了一个v1.24版本的安装.写得不咋样,但是能用.最近不高产了,没灵感了 = . = 手动部署:https://github.com/cby-chen/Kubernetes ...
- [Java]算法练习:新农村建设
1 题目描述 from 网友 CASE1 输入 A1 A8 输出 [A1,A2,A3,A4,A5,A6,A7,A8] CASE2 输入 A1 K1 输出 [A1,B1,C1,D1,E1,F1,G1,H ...
- 百度松果菁英班--oj赛(第二次)
目录 一.小码哥剪绳子 二.咖啡品鉴师小码哥 三.均分糖果 四.持盾 五.活动安排 六.甜品供应 七.斐波那契数列的组合 八.小码哥的布阵指挥 九.活动分组 十.外卖递送 一.小码哥剪绳子 题目:马上 ...
- Java SpringBoot 中,动态执行 bean 对象中的方法
根据不同的条件,调用不同的 bean 对象,执行对象中的方法 SpringUtils 工具类 package com.vipsoft.web.utils; import cn.hutool.core. ...
- 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(14)-Charles过滤网络请求
1.简介 在日常工作测试中,经常要抓包看请求的request,response是不是传的对,返回的字段值对不对,众多的请求中看得眼花缭乱,如何找到自己想要的请求,那么我们就需要过滤请求.Charles ...
- 5221. 【GDOI2018模拟7.10】A
题目大意: 给你一棵有根树,问你在这棵树上总共有多少棵子树的节点构成了一个完整的整数区间. 考试想法: 考试时就想到了正解,正解就是从下到上遍历整一棵树,每一个节点记录一下它的最小值min.最大值ma ...
- Sentinel为什么这么强,我扒了扒背后的实现原理
大家好,我是三友~~ 最近我在整理代码仓库的时候突然发现了被尘封了接近两年之久的Sentinel源码库 两年前我出于好奇心扒了一下Sentinel的源码,但是由于Sentinel本身源码并不复杂,在简 ...