uniapp + vue3 实现暗黑模式手动切换

思路:控制每个页面的根节点类名进行主题切换

技术栈: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

 

uniapp是一个基于Vue.js的跨平台开发框架,而Vue3是Vue.js的最新版本。它们的结合可以带来更好的开发体验和性能优化。uniapp提供了导航栏双页切换的功能,而Vue3的Pinia框架则提供了参数输出和方法调用的功能,还支持模块化和持久化存储。如果您有关于uniappVue3的使用问题,您可以查看uniapp官网获取更详细的信息和示例代码。uniapp在早期版本中开始支持Vue3的使用,并且从HBuilderX 3.2版本开始支持创建基于Vue3的uniapp项目。使用uniappVue3开发项目的流程与常规的Vue3开发类似。您可以按照官方提供的升级指南和使用文档来进行开发。希望以上信息对您有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [uniapp+vue3+pinia框架(模块化+持久化存储)](https://download.csdn.net/download/qq_35079107/87910679)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [uniapp + vue3微信小程序开发(1)框架搭建](https://blog.csdn.net/qq_39404437/article/details/124345386)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [uniapp开发:uniapp切换vue3,一直使用一直爽](https://blog.csdn.net/qq_42961150/article/details/121375073)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值