思路:控制每个页面的根节点类名进行主题切换
技术栈:scss + pinia + vue3组合式函数
最后会有优化过后的代码,使用起来还是比较好理解的
1.引入pinia
// 在main.js中引入pinia
import App from './App'
import * as Pinia from 'pinia';
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
app.use(Pinia.createPinia());
return {
app,
Pinia,
}
}
2.使用pinia
在根目录创建stores文件夹 并创建theme.js文件
// theme.js
import {
defineStore
} from 'pinia'
export const useModifyTheme = defineStore('theme', {
state: () => {
return {
isDark: uni.getStorageSync('isDark') || false, // 控制主题开关
themeClass: uni.getStorageSync('theme') || 'dark' // 主题名
}
},
getters: {
determineTheTheme(state) {
return state.isDark ? 'light' : 'dark' //开关为true返回'light',否则返回'dark'
}
},
actions: {
modifyThemeHanlder(e) {
//
this.isDark = e
this.themeClass = this.determineTheTheme
// 把值存本地
uni.setStorageSync('theme', this.themeClass)
uni.setStorageSync('isDark', this.isDark)
},
setNavigationBarColorHandler() {
const {
themeClass
} = this
// 这里主要是改变tabbar和导航栏的颜色
const darkNavigationBar = {
frontColor: '#000000',
backgroundColor: '#ffffff',
animation: {
duration: 0,
timingFunc: 'easeIn'
}
}
const lightNavigationBar = {
frontColor: '#ffffff',
backgroundColor: '#000000',
animation: {
duration: 0,
timingFunc: 'easeIn'
}
}
const tabBarStyle = {
color: themeClass === 'dark' ? '#000000' : '#ffffff',
selectedColor: '#76C8F9',
backgroundColor: themeClass === 'dark' ? '#ffffff' : '#000000',
borderStyle: 'black'
}
uni.setNavigationBarColor((themeClass === 'dark') ? darkNavigationBar : lightNavigationBar);
const tabBarPages = ['pages/index/index', 'pages/shopping/shopping', 'pages/consultant/consultant',
'pages/cart/cart', 'pages/mine/mine'
] // TabBar 页面路径
// 判断当前页面是否是 TabBar 页面
const currentPages = getCurrentPages()
const currentPage = currentPages[currentPages.length - 1]
if (tabBarPages.includes(currentPage.route)) {
uni.setTabBarStyle(tabBarStyle)
}
},
}
})
3.切换暗黑模式页面
在页面使用的时候需要在每个页面的根节点上都加上theme.themeClass,这点是比较麻烦,目前我还没有想到更好的解决办法,这个页面是控制切换暗黑模式
// setGeneral.vue
<template>
<view class="theme.themeClass">
<!-- 通用设置 -->
暗黑模式切换
<!-- u-swich 是引用了u-view框架 -->
<u-switch v-model="theme.isDark" @change="modifyHanlder" size="56"></u-switch>
</view>
</template>
<script setup>
import { ref } from "vue";
import {useModifyTheme} from "@/stores/theme.js"
import { onShow} from '@dcloudio/uni-app';
const theme = useModifyTheme()
const modifyHanlder =(e)=>{
theme.modifyThemeHanlder(e)
theme.setNavigationBarColorHandler()
}
onShow(()=>{
theme.setNavigationBarColorHandler();
})
</script>
4.在其他组件页面中使用
因为在script中的代码每个页面都需要使用一次,如果每个页面都复制一遍这个代码,看起来会比较臃肿,这个是示例,后面会用组合式函数进行封装
//index.vue
<template>
<view :class="theme.themeClass">
<view>
Dark and light
</view>
</view>
</template>
<script setup>
import { useModifyTheme } from '@/stores/theme.js';
import { onShow } from '@dcloudio/uni-app';
const theme = useModifyTheme();
onShow(()=>{
console.log(theme.themeClass);
theme.setNavigationBarColorHandler();
})
</script>
5.封装组合式函数
封装的目的在于使用时代码更少,使用稍微不那么麻烦点...
为什么用稍微.. 因为还是需要在每个页面引入...
在根目录创建一个hooks文件夹,在文件夹中创建一个useTheme.js文件
// useTheme.js
import {
useModifyTheme
} from '@/stores/theme.js';
import {
onShow
} from '@dcloudio/uni-app';
import {
storeToRefs
} from 'pinia'
export function useTheme() {
// 被组合式函数封装和管理的状态
const theme = useModifyTheme();
const { themeClass } = storeToRefs(theme)
const {
setNavigationBarColorHandler
} = theme
onShow(() => {
setNavigationBarColorHandler();
})
// 通过返回值暴露所管理的状态
return {
themeClass
}
}
6.在页面使用组合式函数
这时候的页面只需要引入组合式函数就可以了,看起来是不是精简了很多,
可以和第4步使用进行比较....
// index.vue
<template>
<view :class="themeClass">
<view>
Dark and light
</view>
</view>
</template>
<script setup>
import { useTheme } from '@/hooks/useTheme.js';
const { themeClass } = useTheme();
</script>
7.创建scss文件
这里的样式可以根据自己的需求更改
// theme.scss
$q-white:#fff;
$q-black:#000000;
.dark {
background-color: #e8e8e8;
color:$q-black;
}
.light {
background-color:$q-black;
color: $q-white;
}
创建的scss文件需要在app.vue中声明,就可以全局使用了
// app.vue
<style lang="scss">
@import '@/common/theme.scss'
</style>
8.效果图
//dark
// light