文章目录
- vue Pinia 全局主题切换
- 基本环境
- 结果展示
- 过程解析
vue Pinia 全局主题切换
目的 : 实现单页面上切换主题,例如 关灯或开灯;
环境: vue3.0 + vite + Pinia
基本环境
// tsconfig.json 文件中 新增路径配置 导入自定义文件时可以之间@导入
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*":["src/*"]
}
},
}
// main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia'
import router from '@/router/router'
// 创建app为vue实例根组件或全局组件;
const app = createApp(App)
// vue实例添加router组件
app.use(router)
// vue实例添加pinia组件
app.use(createPinia())
// vue实例挂载到index.html页面
app.mount('#app')
// app.vue
<script setup lang="ts">
// 导入引入的组件
import { NConfigProvider,NGlobalStyle, zhCN, dateZhCN,useOsTheme} from 'naive-ui'
import {useThemeStore} from '@/store/theme'
// themeStore 主题实例
const themeStore = useThemeStore()
</script>
<template>
<!-- 全局处理 颜色组件 -->
<n-config-provider
:theme="themeStore.theme"
:locale="zhCN"
:date-locale="dateZhCN">
<!-- 组件渲染出口 -->
<router-view></router-view>
<n-global-style />
</n-config-provider>
</template>
默认路由router加载
/
路径,所以新建了一个index.vue
用来组装页面;
// ViewHead.vue 页面 头部组件,导入到index.vue中
<script lang="ts" setup>
import { onMounted,ref,reactive,computed,onBeforeMount,onUpdated,onUnmounted,watch} from 'vue';
import {NButton,useOsTheme} from 'naive-ui'
import { update } from 'lodash';
import {useThemeStore} from '@/store/theme'
// 主题标记
const themeFlag=ref(true)
// themeStore
const theme = useThemeStore()
// 获取当前系统主题
const osTheme = useOsTheme();
// 监听当前操作系统主题
watch(osTheme,osTheme=>{
if(osTheme){
if(osTheme==="dark"){
themeFlag.value=true
}else{
themeFlag.value=false
}
updateTheme()
}
},{
// 第一次绑定时会初始化立即执行一次
immediate:true
})
// 变更主题
function updateTheme(){
themeFlag.value=!themeFlag.value
theme.setTheme(themeFlag.value);
}
</script>
<template>
<h2>测试{{ "haha" }}</h2>
<n-button @click="updateTheme" strong secondary type="success">
{{themeFlag?"光明":"黑暗"}}
</n-button>
</template>
<style lang="less" scoped>
</style>
Pinia Store 组件的使用,用来缓存主题的全局状态
import {darkTheme,lightTheme} from 'naive-ui'
import { defineStore } from 'pinia'
import { ref, watch} from 'vue'
import type {GlobalTheme} from 'naive-ui'
// themeStore of pinia
export const useThemeStore = defineStore('themeStore',()=>{
// theme ref var
const theme = ref<GlobalTheme>(lightTheme)
// actions: update Theme
function setTheme(themes:boolean){
if(themes){
// true lightTheme
theme.value = lightTheme
}else{
// false darkTheme
theme.value = darkTheme
}
}
return {
theme,
setTheme
}
})
目录结构
src
├─api
├─assets
├─components
├─router
├─store
├─theme.ts
├─view
├─fixedcomponent
├─ViewHead.vue
├─index.vue
App.vue
main.ts
结果展示
过程解析
因为使用了
NaiveUI
所以就使用了其支持的全局化配置Config Provider
即: App.vue 中的<n-config-provider>
标签 ,包裹整个页面的渲染出口;
因为触发切换的组件在
ViewHead.vue
子组件内所以需要使用 Pinia storetheme.ts
来存储全局的主题状态变化和主题变更的触发;
在
ViewHead.vue
中使用 n-button 按钮即可 通过 useThemeStore()中的setTheme()方法修改其theme的状态属性, 进而改变n-config-provider
标签的:theme属性
实现初次加载页面时根据系统的主题来修改页面的theme主题状态, 在
ViewHead.vue
中通过watch监听useOsTheme()
即可实现;