refactor: useResize hook

This commit is contained in:
pany 2022-08-22 16:57:55 +08:00
parent 4583495aa3
commit 07158c8db4
3 changed files with 64 additions and 91 deletions

View File

@ -0,0 +1,51 @@
import { watch, onBeforeMount, onMounted, onBeforeUnmount } from "vue"
import { useRoute } from "vue-router"
import { useAppStore, DeviceType } from "@/store/modules/app"
/** 参考 Bootstrap 的响应式设计 WIDTH = 992 */
const WIDTH = 992
/** 根据大小变化重新布局 */
export default () => {
const route = useRoute()
const appStore = useAppStore()
const _isMobile = () => {
const rect = document.body.getBoundingClientRect()
return rect.width - 1 < WIDTH
}
const _resizeHandler = () => {
if (!document.hidden) {
const isMobile = _isMobile()
appStore.toggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop)
if (isMobile) {
appStore.closeSidebar(true)
}
}
}
watch(
() => route.name,
() => {
if (appStore.device === DeviceType.Mobile && appStore.sidebar.opened) {
appStore.closeSidebar(false)
}
}
)
onBeforeMount(() => {
window.addEventListener("resize", _resizeHandler)
})
onMounted(() => {
if (_isMobile()) {
appStore.toggleDevice(DeviceType.Mobile)
appStore.closeSidebar(true)
}
})
onBeforeUnmount(() => {
window.removeEventListener("resize", _resizeHandler)
})
}

View File

@ -1,25 +1,22 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onBeforeMount, onBeforeUnmount, onMounted, reactive } from "vue" import { computed } from "vue"
import { useAppStore, DeviceType } from "@/store/modules/app" import { useAppStore, DeviceType } from "@/store/modules/app"
import { useSettingsStore } from "@/store/modules/settings" import { useSettingsStore } from "@/store/modules/settings"
import { AppMain, NavigationBar, Settings, Sidebar, TagsView, RightPanel } from "./components" import { AppMain, NavigationBar, Settings, Sidebar, TagsView, RightPanel } from "./components"
import useResize from "./useResize" import useResize from "./hooks/useResize"
const appStore = useAppStore() const appStore = useAppStore()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
const { sidebar, device, addEventListenerOnResize, resizeMounted, removeEventListenerResize, watchRouter } = useResize()
const state = reactive({ /** Layout 布局响应式 */
handleClickOutside: () => { useResize()
appStore.closeSidebar(false)
}
})
const classObj = computed(() => { const classObj = computed(() => {
return { return {
hideSidebar: !sidebar.value.opened, hideSidebar: !appStore.sidebar.opened,
openSidebar: sidebar.value.opened, openSidebar: appStore.sidebar.opened,
withoutAnimation: sidebar.value.withoutAnimation, withoutAnimation: appStore.sidebar.withoutAnimation,
mobile: device.value === DeviceType.Mobile mobile: appStore.device === DeviceType.Mobile
} }
}) })
const showSettings = computed(() => { const showSettings = computed(() => {
@ -31,22 +28,14 @@ const showTagsView = computed(() => {
const fixedHeader = computed(() => { const fixedHeader = computed(() => {
return settingsStore.fixedHeader return settingsStore.fixedHeader
}) })
const handleClickOutside = () => {
watchRouter() appStore.closeSidebar(false)
onBeforeMount(() => { }
addEventListenerOnResize()
})
onMounted(() => {
resizeMounted()
})
onBeforeUnmount(() => {
removeEventListenerResize()
})
</script> </script>
<template> <template>
<div :class="classObj" class="app-wrapper"> <div :class="classObj" class="app-wrapper">
<div v-if="classObj.mobile && sidebar.opened" class="drawer-bg" @click="state.handleClickOutside" /> <div v-if="classObj.mobile && classObj.openSidebar" class="drawer-bg" @click="handleClickOutside" />
<Sidebar class="sidebar-container" /> <Sidebar class="sidebar-container" />
<div :class="{ hasTagsView: showTagsView }" class="main-container"> <div :class="{ hasTagsView: showTagsView }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }"> <div :class="{ 'fixed-header': fixedHeader }">

View File

@ -1,67 +0,0 @@
import { computed, watch } from "vue"
import { useRoute } from "vue-router"
import { useAppStore, DeviceType } from "@/store/modules/app"
/** 参考 Bootstrap 的响应式设计 WIDTH = 992 */
const WIDTH = 992
/** 根据大小变化重新布局 */
export default () => {
const route = useRoute()
const appStore = useAppStore()
const device = computed(() => {
return appStore.device
})
const sidebar = computed(() => {
return appStore.sidebar
})
const watchRouter = watch(
() => route.name,
() => {
if (appStore.device === DeviceType.Mobile && appStore.sidebar.opened) {
appStore.closeSidebar(false)
}
}
)
const isMobile = () => {
const rect = document.body.getBoundingClientRect()
return rect.width - 1 < WIDTH
}
const resizeMounted = () => {
if (isMobile()) {
appStore.toggleDevice(DeviceType.Mobile)
appStore.closeSidebar(true)
}
}
const resizeHandler = () => {
if (!document.hidden) {
appStore.toggleDevice(isMobile() ? DeviceType.Mobile : DeviceType.Desktop)
if (isMobile()) {
appStore.closeSidebar(true)
}
}
}
const addEventListenerOnResize = () => {
window.addEventListener("resize", resizeHandler)
}
const removeEventListenerResize = () => {
window.removeEventListener("resize", resizeHandler)
}
return {
device,
sidebar,
resizeMounted,
addEventListenerOnResize,
removeEventListenerResize,
watchRouter
}
}