refactor: 将多主题功能从 pinia 抽离为 hook

This commit is contained in:
pany 2022-10-17 15:04:27 +08:00
parent e41d1f21a5
commit 281a7bebbf
6 changed files with 54 additions and 53 deletions

View File

@ -1,11 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useAppStore } from "@/store/modules/app" import { useTheme } from "@/hooks/useTheme"
import zhCn from "element-plus/lib/locale/lang/zh-cn" import zhCn from "element-plus/lib/locale/lang/zh-cn"
const appStore = useAppStore() const { initTheme } = useTheme()
/** 初始化主题 */ /** 初始化主题 */
appStore.initTheme() initTheme()
/** 将 Element-Plus 的语言设置为中文 */ /** 将 Element-Plus 的语言设置为中文 */
const locale = zhCn const locale = zhCn
</script> </script>

View File

@ -1,17 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from "vue" import { useTheme } from "@/hooks/useTheme"
import { useAppStore } from "@/store/modules/app" import type { ThemeName } from "@/hooks/useTheme"
import themeList from "@/config/theme"
import type { ThemeName } from "@/config/theme"
import { MagicStick } from "@element-plus/icons-vue" import { MagicStick } from "@element-plus/icons-vue"
const appStore = useAppStore() const { themeList, activeThemeName, setTheme } = useTheme()
const activeThemeName = computed(() => {
return appStore.activeThemeName
})
const handleSetTheme = (name: ThemeName) => { const handleSetTheme = (name: ThemeName) => {
appStore.setTheme(name) setTheme(name)
} }
</script> </script>

View File

@ -1,20 +0,0 @@
/** 注册的主题, 其中 normal 是必须的, dark 是内置的, 如需更多主题,可自行注册 */
export type ThemeName = "normal" | "dark"
interface IThemeList {
title: string
name: ThemeName
}
const themeList: IThemeList[] = [
{
title: "默认",
name: "normal"
},
{
title: "黑暗",
name: "dark"
}
]
export default themeList

44
src/hooks/useTheme.ts Normal file
View File

@ -0,0 +1,44 @@
import { ref } from "vue"
import { getActiveThemeName, setActiveThemeName } from "@/utils/cache/localStorage"
interface IThemeList {
title: string
name: ThemeName
}
/** 注册的主题名称, 其中 normal 是必填的 */
export type ThemeName = "normal" | "dark"
/** 主题 hook */
export function useTheme() {
/** 主题列表 */
const themeList: IThemeList[] = [
{
title: "默认",
name: "normal"
},
{
title: "黑暗",
name: "dark"
}
]
/** 正在应用的主题名称 */
const activeThemeName = ref<ThemeName>(getActiveThemeName() || "normal")
const initTheme = () => {
setHtmlClassName(activeThemeName.value)
}
const setTheme = (value: ThemeName) => {
activeThemeName.value = value
setHtmlClassName(activeThemeName.value)
setActiveThemeName(activeThemeName.value)
}
/** 在 html 根元素上挂载 class */
const setHtmlClassName = (value: ThemeName) => {
document.documentElement.className = value
}
return { themeList, activeThemeName, initTheme, setTheme }
}

View File

@ -1,7 +1,6 @@
import { reactive, ref } from "vue" import { reactive, ref } from "vue"
import { defineStore } from "pinia" import { defineStore } from "pinia"
import { getSidebarStatus, getActiveThemeName, setSidebarStatus, setActiveThemeName } from "@/utils/cache/localStorage" import { getSidebarStatus, setSidebarStatus } from "@/utils/cache/localStorage"
import type { ThemeName } from "@/config/theme"
export enum DeviceType { export enum DeviceType {
Mobile, Mobile,
@ -13,18 +12,12 @@ interface ISidebar {
withoutAnimation: boolean withoutAnimation: boolean
} }
const setClassName = (value: ThemeName) => {
document.documentElement.className = value
}
export const useAppStore = defineStore("app", () => { export const useAppStore = defineStore("app", () => {
const sidebar: ISidebar = reactive({ const sidebar: ISidebar = reactive({
opened: getSidebarStatus() !== "closed", opened: getSidebarStatus() !== "closed",
withoutAnimation: false withoutAnimation: false
}) })
const device = ref<DeviceType>(DeviceType.Desktop) const device = ref<DeviceType>(DeviceType.Desktop)
/** 正在应用的主题的名字 */
const activeThemeName = ref<ThemeName>(getActiveThemeName() || "normal")
const toggleSidebar = (withoutAnimation: boolean) => { const toggleSidebar = (withoutAnimation: boolean) => {
sidebar.opened = !sidebar.opened sidebar.opened = !sidebar.opened
@ -43,17 +36,6 @@ export const useAppStore = defineStore("app", () => {
const toggleDevice = (value: DeviceType) => { const toggleDevice = (value: DeviceType) => {
device.value = value device.value = value
} }
const setTheme = (value: ThemeName) => {
activeThemeName.value = value
// 应用到 Dom
setClassName(activeThemeName.value)
// 持久化
setActiveThemeName(activeThemeName.value)
}
const initTheme = () => {
// 初始化
setClassName(activeThemeName.value)
}
return { device, sidebar, activeThemeName, toggleSidebar, closeSidebar, toggleDevice, setTheme, initTheme } return { device, sidebar, toggleSidebar, closeSidebar, toggleDevice }
}) })

View File

@ -1,7 +1,7 @@
/** 统一处理 localStorage */ /** 统一处理 localStorage */
import CacheKey from "@/constants/cacheKey" import CacheKey from "@/constants/cacheKey"
import type { ThemeName } from "@/config/theme" import type { ThemeName } from "@/hooks/useTheme"
export const getSidebarStatus = () => { export const getSidebarStatus = () => {
return localStorage.getItem(CacheKey.SIDEBAR_STATUS) return localStorage.getItem(CacheKey.SIDEBAR_STATUS)