From 96c30a6d83d44e70844cd7b59221d7ed005d666a Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 28 Apr 2020 16:00:41 -0400 Subject: [PATCH] refactor router/content --- lib/app/components/Content.js | 48 ++--------------------- lib/app/composables/router.js | 72 +++++++++++++++++++++++++++++------ lib/theme-default/Layout.vue | 8 ++-- 3 files changed, 69 insertions(+), 59 deletions(-) diff --git a/lib/app/components/Content.js b/lib/app/components/Content.js index 1b3909be..0642e3a5 100644 --- a/lib/app/components/Content.js +++ b/lib/app/components/Content.js @@ -1,49 +1,9 @@ -import { h, shallowRef, watchEffect, inject, nextTick } from 'vue' -import { RouteSymbol } from '../composables/router' -import Theme from '/@theme/index' - -const NotFound = Theme.NotFound || (() => '404 Not Found') +import { h } from 'vue' +import { useRoute } from '../composables/router' export const Content = { setup() { - const comp = shallowRef() - - if (typeof window !== 'undefined') { - const route = inject(RouteSymbol, { - path: '/', - scrollPosition: 0 - }) - - watchEffect(() => { - const pendingPath = route.path - let pagePath = pendingPath.replace(/\.html$/, '') - if (pagePath.endsWith('/')) { - pagePath += 'index' - } - - // awlays force re-fetch content in dev - import(`${pagePath}.md?t=${Date.now()}`) - .then(async (m) => { - if (route.path === pendingPath) { - comp.value = m.default - await nextTick() - window.scrollTo({ - left: 0, - top: route.scrollPosition, - behavior: 'auto' - }) - } - }) - .catch((err) => { - if (route.path === pendingPath) { - comp.value = NotFound - } - }) - }) - } else { - // TODO SSR - } - - return () => (comp.value ? h(comp.value) : null) + const route = useRoute() + return () => (route.component ? h(route.component) : null) } } diff --git a/lib/app/composables/router.js b/lib/app/composables/router.js index c8f5e307..171b5613 100644 --- a/lib/app/composables/router.js +++ b/lib/app/composables/router.js @@ -1,16 +1,31 @@ -import { reactive, provide } from 'vue' +import { shallowReactive, provide, inject, nextTick } from 'vue' +import Theme from '/@theme/index' + +const NotFound = Theme.NotFound || (() => '404 Not Found') /** - * @type {import('vue').InjectionKey<{ path: string, scrollPosition: number }>} + * @typedef {{ + * path: string + * component: import('vue').Component | null + * }} Route */ -export const RouteSymbol = Symbol() + +/** + * @type {import('vue').InjectionKey} + */ +const RouteSymbol = Symbol() + +/** + * @returns {Route} + */ +const getDefaultRoute = () => ({ + path: location.pathname, + component: null +}) export function useRouter() { const loc = location - const route = reactive({ - path: loc.pathname, - scrollPosition: window.scrollY - }) + const route = shallowReactive(getDefaultRoute()) window.addEventListener( 'click', @@ -41,8 +56,7 @@ export function useRouter() { // save scroll position before changing url saveScrollPosition() history.pushState(null, '', href) - route.path = loc.pathname - route.scrollPosition = 0 + loadPage(route) } } } @@ -56,12 +70,48 @@ export function useRouter() { * @param {*} e */ (e) => { - route.path = location.pathname - route.scrollPosition = (e.state && e.state.scrollPosition) || 0 + loadPage(route, (e.state && e.state.scrollPosition) || 0) } ) provide(RouteSymbol, route) + + loadPage(route) +} + +export function useRoute() { + return inject(RouteSymbol) || getDefaultRoute() +} + +/** + * @param {Route} route + * @param {number} scrollPosition + */ +function loadPage(route, scrollPosition = 0) { + const pendingPath = (route.path = location.pathname) + let pagePath = pendingPath.replace(/\.html$/, '') + if (pagePath.endsWith('/')) { + pagePath += 'index' + } + + // awlays force re-fetch content in dev + import(`${pagePath}.md?t=${Date.now()}`) + .then(async (m) => { + if (route.path === pendingPath) { + route.component = m.default + await nextTick() + window.scrollTo({ + left: 0, + top: scrollPosition, + behavior: 'auto' + }) + } + }) + .catch((err) => { + if (route.path === pendingPath) { + route.component = NotFound + } + }) } function saveScrollPosition() { diff --git a/lib/theme-default/Layout.vue b/lib/theme-default/Layout.vue index 6d3124cb..fe44ed1e 100644 --- a/lib/theme-default/Layout.vue +++ b/lib/theme-default/Layout.vue @@ -1,10 +1,10 @@