uni-app使用scss修改皮肤2
继续接上次的话题,uni-app做皮肤功能。上次我再uni-app使用scss修改皮肤文章中写到用scss做皮肤。但是后面我意识到,用scss做皮肤,必须每次启动才会生效,在项目中,我们不可能因为某个用户修改了皮肤就重新启动一次服务, 所以上次的方法对于开发者可行,但是对于项目实施,是不可取的.既然不可取,那我们另寻他法。 看到网上很多说使用document去设置data-theme属性,我不否定这种方法在h5中确实是生效的,但是在微信小程序中,根本就没有document属性,所以这种方法是不可取的。
说一下我还皮肤的实现方法。对于小程序,换肤无非三个地方: 1. 顶部导航栏的颜色。 2. 主体中的重要信息已经按钮等颜色。 3. tabbar上的字体颜色与图片。
首先如果用户没有登录,那么我们就显示默认皮肤,如果用户登录了,我们就根据用户的设置,显示用户的设置的颜色。 并且我会把用户的皮肤配置放在vuex中(毕竟每一页都需要换颜色)
第一步: 首先在vuex中写功能逻辑
state: { themeMode: 'light', //当前颜色模式 light/dark themeColor: '#3964f9', //当前主题颜色 }, mutations: { setCurThemeColor(state, data) { state.themeColor = data uni.setStorageSync("themeColor", data); // #ifdef H5 window.document.documentElement.setAttribute('data-color', data); // #endif }, setCurThemeMode(state, data) { state.themeMode = data uni.setStorageSync("themeMode", data); // #ifdef H5 window.document.documentElement.setAttribute('data-theme', data); //做h5箭筒 // #endif }, }, actions: { getTheme(context) { request(api.chooseSkin, {}, 'get').then(res => { const { config, //用户的颜色配置 skinId, isDark, //是否是夜晚模式 isAuto //自动切换白天与夜晚模式 } = res; if (isDark == 1) { context.commit('setCurThemeMode', 'dark') } else { context.commit('setCurThemeMode', 'light') } context.commit('setCurThemeColor', config.hex) context.commit('setConfigColor', config) }).catch(res => { uni.showToast({ title: res[0] }); }); },
第二步:在app.vue中做请求,让用户在进入程序的时候,根据缓存去获取皮肤,如果没有用户的登录缓存,那就显示默认的皮肤颜色。
methods: { ...mapActions([ 'getTheme' // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` ]), ...mapMutations(['LOGIN_IN', 'LOGIN_OUT', 'setCurThemeMode', 'setCurThemeColor']), handleSetTabBar() { const themeMode = uni.getStorageSync('themeMode'); if (themeMode) { this.setCurThemeMode(themeMode); if (themeMode === 'dark') { uni.setTabBarStyle({ color: '#666', selectedColor: store.state.themeColor, backgroundColor: '#2B3757' }); } else { uni.setTabBarStyle({ color: '#666', selectedColor: store.state.themeColor, backgroundColor: '#fff' }); } } else { store.commit('setCurThemeMode', 'light'); // #ifdef H5 window.document.documentElement.setAttribute('data-theme', 'light'); // #endif } }, handleSetColor() { const themecolor = uni.getStorageSync('themeColor'); if (themecolor) { this.setColor(themecolor); } else { store.commit('setCurThemeColor', '#3964f9'); // #ifdef H5 window.document.documentElement.setAttribute('data-color', '#3964f9'); // #endif } } }, onLaunch: function() { const loginInfo = uni.getStorageSync('loginInfo'); if (loginInfo.token) { this.LOGIN_IN(loginInfo); } else { this.LOGIN_OUT(); } //设置tabbar颜色 this.handleSetTabBar(); //设置顶部颜色 this.handleSetColor(); this.getTheme(); },
第三步: 我们还是得靠css实现, 定义好主题色
:root[data-color='#3964f9'] { --hex: #3964f9; } :root[data-color='#C71585'] { --hex: #c71585; } :root[data-color='#f63e3e'] { --hex: #f63e3e; } :root[data-color='#f2c659'] { --hex: #f2c659; } :root[data-theme='light'] { --nav: #3964f9; } :root[data-theme='dark'] { --nav: #3964f9; } page-meta[data-theme='dark'] { --nav: #3964f9; } page-meta[data-theme='light'] { --nav: #3964f9; }
最后一步: 在页面是使用
<page-meta :data-theme="themeMode" :data-color="themeColor"> <view class="content"></view> </page-meta> onReady() { const themecolor = uni.getStorageSync('themeColor'); this.setColor(themecolor); //每一页在页面上去设置修改顶部导航栏的颜色, 没法,page.json中写了默认颜色,就只能每一页去修改 }, .btn-main { background-color: var(--hex); color: $fff; }
注意: 因为setColor函数每一个页都需要使用,所以我们用mixin抽离出来,并且在main中引入
import themeMixin from '@/common/theme'; Vue.mixin(themeMixin); setColor(bg, fg) { uni.setNavigationBarColor({ // 字体颜色 仅支持 #ffffff 和 #000000 frontColor: fg || '#ffffff', // 背景颜色值,有效值为十六进制颜色 backgroundColor: bg || '#3964f9', animation: { duration: 250, // 动画时间 timingFunc: 'easeIn' //linear/easeOut/easeInOut } }); // 关闭加载条 uni.hideNavigationBarLoading() },
到这里就大功告成了,这篇文章是在我做完功能后写的,可能有漏掉一些代码,但是大致的方向在这里了