refactor router/content

pull/1/head
Evan You 4 years ago
parent c4002a8d2e
commit 96c30a6d83

@ -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)
}
}

@ -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<Route>}
*/
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() {

@ -1,10 +1,10 @@
<template>
<div class="theme-container">
<h1>Hello VitePress</h1>
<pre>{{ $site }}</pre>
<pre>{{ $page }}</pre>
<pre>{{ site }}</pre>
<pre>{{ page }}</pre>
<pre>$site {{ $site }}</pre>
<pre>$page {{ $page }}</pre>
<pre>useSiteData() {{ site }}</pre>
<pre>usePageData() {{ page }}</pre>
<Content/>
</div>
</template>

Loading…
Cancel
Save