在上一篇 “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