主题切换功能
功能说明
用于前端相同布局,不同样式的切换(黑、白主题样式切换),兼容H5、APP
- 所需依赖
npm install --save css-vars-ponyfill vuex
前置条件:配置好 vuex
第一步
于已配置好的 vuex 内配置 store/index.js 跟 store/module/theme.js
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import theme from './module/theme'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
theme
},
})
export default store
// store/module/theme.js
import cssVars from 'css-vars-ponyfill';
// 自定义的缓存方法 建议使用 uni.setStorageSync,具体自行自行去相应网站查阅
import {
setCookie,
getCookie
} from '@/xxx.js'
const themeNameArr = [
'dark',
'light'
]
const THEME_KEY = 'theme'
const THEME_STYLE_KEY = 'themeStyle'
export default {
namespaced: true,
state: {
theme: getCookie(THEME_KEY) || 'dark', // 枚举值:dark、light
themeStyle: ''
},
mutations: {
setTheme(state, key) {
state.theme = key
setCookie(THEME_KEY, key ? key : themeNameArr[0])
},
setThemeStyle(state, key) {
state.themeStyle = key
setCookie(THEME_STYLE_KEY, key)
},
},
actions: {
async setThemeNav({
state,
dispatch
}, theme = '') {
// true 黑 false 白
let judge = theme || await dispatch('getTheme')
uni.setNavigationBarColor({
frontColor: judge ? '#ffffff' : '#000000',
backgroundColor: judge ? '#181825' : '#ffffff',
animation: {
duration: 0,
timingFunc: 'easeIn'
}
})
uni.setTabBarStyle({
// tab 上的文字默认颜色
color: judge ? '#8A8D9F' : '#000000',
// tab 上的文字选中时的颜色
selectedColor: judge ? '#0CC993' : '#0CC993',
// tab 的背景色
backgroundColor: judge ? '#272934' : '#FFFFFF',
// tabBar上边框的颜色, 仅支持 black/white
borderStyle: judge ? 'black' : 'white'
})
},
async changeTheme({
commit,
state,
dispatch
}, theme = '') {
let key = await dispatch('getTheme') ? themeNameArr[1] : themeNameArr[0]
commit('setTheme', theme || key)
dispatch('initTheme')
// 切换刷新
// #ifdef H5
window.location.reload()
// #endif
// #ifdef APP-PLUS
// plus.runtime.restart()
// #endif
},
async getStyleJson({
state,
dispatch
}) {
// 判断主题 true 黑 false 白
let judge = await dispatch('getTheme')
return {
'--font-color': `${judge ? '#FFFFFF' : '#272934'}`,
'--theme-color': '#0CC993',
}
},
// style 样式,JSON 对象转字符串
getStyleStr({
state
}, style) {
let s = []
for (let i in style) {
s.push(i + ':' + style[i]);
}
s = s.join(';')
return s
},
initTheme({
commit,
dispatch
}) {
dispatch('getStyleJson').then(async res => {
let style = await dispatch('getStyleStr', res)
commit('setThemeStyle', style)
// #ifdef H5
cssVars({
watch: true,
variables: res,
// 当添加,删除或修改其<link>或<style>元素的禁用或href属性时,ponyfill将自行调用
onlyLegacy: true, // false 默认将css变量编译为浏览器识别的css样式 true 当浏览器不支持css变量的时候将css变量编译为识别的css
});
// #endif
})
},
getTheme({
state
}) {
// true 黑 false 白
return state.theme === themeNameArr[0]
}
}
};
第二步
于新建 common 文件夹下新建 themeMixins.js
// themeMixins.js
import {
mapState,
mapActions
} from 'vuex'
const getThemeStyleMixins = () => {
return {
onLoad() {
// APP 环境每次引入
// #ifdef APP-PLUS
this.initTheme()
// #endif
},
computed: {
...mapState('theme', ['theme', 'themeStyle']),
getThemeStyle() {
// #ifdef H5
return this.themeStyle
// #endif
// #ifdef APP-PLUS
return this.themeStyle
// #endif
}
},
onShow() {
// getCurrentPages 判断页面存在, globalData 判断主要是不在 App 混入
if(getCurrentPages().length && !this.globalData) {
this.$nextTick(() => {
this.setThemeNav()
})
}
},
methods: {
...mapActions('theme', ['changeTheme', 'initTheme', 'setThemeNav', 'getTheme'])
}
}
}
export default getThemeStyleMixins
第三步
- 于
main.js混入themeMixins.js
// main.js
import Vue from 'vue'
import App from './App'
import store from './store'
import themeMixins from '@/common/themeMixins.js';
Vue.mixin(themeMixins());
Vue.config.productionTip = false
Vue.prototype.$store = store
App.mpType = 'app'
const app = new Vue({
store,
...App
})
- 于
APP.vue配置混入的initTheme方法
export default {
onLaunch: function() {
// #ifdef H5
this.initTheme()
// #endif
}
}
第四步
- 于每个页面的根
view标签处配置themeStyle样式
<template>
<view :style="themeStyle"></view>
<template>
- 通过 css 的
var()函数使用已配置的样式
.demo-wrap {
background: var(--theme-color);
font-size: var(--font-color);
}
Powered by Waline v2.15.8