主题切换/换肤(vue2)
思路:
- 原理:通过var变量的方式实现主题切换
- 全局var变量可以在page选择器中定义,但是没有找到动态修改page选择器中var变量的方法,所以最终只能每个页面都通过
style='--theme-color: #fff";'
这种写法绑定var变量字符串,再基于vuex
和mixin
简化写法 - 使用scss简化var变量写法(可选)
- 页面中使用scss变量或者var变量
- 原理示例:
<template>
<view class="content" :style="style">
<view @click="change">改变</view>
</view>
</template>
<script>
export default {
data() {
return {
style: "--theme-color: #fff"
}
},
methods: {
change() {
this.style =
this.style === "--theme-color: #fff"
? "--theme-color: #000"
: "--theme-color: #fff"
}
}
}
</script>
<style lang="scss">
.content {
background: var(--theme-color);
color: pink;
height: 100vh;
}
</style>
什么是var变量
1.新建store/index.js
设置主题后,获取相应主题的var变量字符串
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
themeName: "light",
themeStyle: {
"light": `
--nav-bg:#42b983;
--nav-color:#ffffff;
`,
"dark": `
--nav-bg:#000;
--nav-color:#ffffff;
`
}
},
getters: {
theme(state) {
return state.themeStyle[state.themeName]
}
},
mutations: {
setTheme(state, themeName = "light") {
state.themeName = themeName
}
}
})
export default store
2.使用mixin
每个页面都需要获取相应主题的var变量字符串,使用mixin进行简化写法
import {
mapState,
mapGetters
} from 'vuex'
export default {
install(Vue) {
Vue.mixin({
computed: {
...mapState({
themeName: 'themeName'
}),
...mapGetters({
theme: "theme"
})
}
})
}
}
3.main.js中导入store
import Vue from 'vue'
import App from './App'
import store from './store'
import mixin from '@/mixin/themeMixin.js'
Vue.use(mixin)
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
4.使用scss简化var变量写法(可选)
uni.scss加入代码
$nav-bg: var(--nav-bg);
$nav-color: var(--nav-color);
页面中使用var变量的写法
<style lang="scss">
.btn {
background-color: var(--nav-bg) !important;
color: var(--nav-color) !important;
}
</style>
页面中使用scss变量的写法
<style lang="scss">
.btn {
background-color: $nav-color !important;
color: $nav-bg !important;
}
</style>
5.切换主题
<template>
<view :style="theme" class="page">
<button @click="setTheme('dark')" class="btn">黑夜</button>
<button @click="setTheme('light')" class="btn">白天</button>
</view>
</template>
<script>
export default {
data() {
return {}
},
methods: {
setTheme(theme) {
this.$store.commit("setTheme", theme)
}
}
}
</script>
<style lang="scss">
.page {
background-color: $nav-bg;
height: 100vh;
}
.btn {
background-color: $nav-color !important;
color: $nav-bg !important;
}
</style>
注意点:不能使用page选择器设置背景色
下方这种写法不能正确切换主题,因为绑定的var变量字符串是绑定在页面最外层元素上的,而page层是页面最外层元素的祖先级(目前没找到办法,更改page层的var变量值)
<template>
<view :style="theme">
</view>
</template>
<style lang="scss">
page {
background-color: $nav-bg;
}
</style>
只能使用这种写法
<template>
<view :style="theme" class="page">
</view>
</template>
<style lang="scss">
.page {
background-color: $nav-bg;
}
</style>
黑白主题
page {
filter: grayscale(100%);
}