feat: support same page navigation in router.go

pull/4511/head
Divyansh Singh 8 months ago
parent e0350275b3
commit 470ccd3f1f

@ -71,10 +71,43 @@ export function createRouter(
go go
} }
async function go(href: string = inBrowser ? location.href : '/') { async function go(
href: string = inBrowser ? location.href : '/',
cause: Element | null = null
) {
href = normalizeHref(href) href = normalizeHref(href)
let loc: string | null = null
if (inBrowser) {
loc = normalizeHref(location.href)
const { pathname, search, hash } = new URL(href, fakeHost)
const currentLoc = new URL(loc, fakeHost)
if (
pathname === currentLoc.pathname &&
search === currentLoc.search &&
hash !== currentLoc.hash
) {
history.pushState({}, '', href)
window.dispatchEvent(
new HashChangeEvent('hashchange', {
oldURL: currentLoc.href,
newURL: href
})
)
if (hash) {
scrollTo(cause, hash, cause?.classList.contains('header-anchor'))
} else {
window.scrollTo(0, 0)
}
return
}
}
if ((await router.onBeforeRouteChange?.(href)) === false) return if ((await router.onBeforeRouteChange?.(href)) === false) return
if (inBrowser && href !== normalizeHref(location.href)) { if (loc !== null && href !== loc) {
// save scroll position before changing url // save scroll position before changing url
history.replaceState({ scrollPosition: window.scrollY }, '') history.replaceState({ scrollPosition: window.scrollY }, '')
history.pushState({}, '', href) history.pushState({}, '', href)
@ -125,20 +158,10 @@ export function createRouter(
} }
if (targetLoc.hash && !scrollPosition) { if (targetLoc.hash && !scrollPosition) {
let target: HTMLElement | null = null scrollTo(null, targetLoc.hash)
try { } else {
target = document.getElementById( window.scrollTo(0, scrollPosition)
decodeURIComponent(targetLoc.hash).slice(1)
)
} catch (e) {
console.warn(e)
}
if (target) {
scrollTo(target, targetLoc.hash)
return
}
} }
window.scrollTo(0, scrollPosition)
}) })
} }
} }
@ -210,39 +233,12 @@ export function createRouter(
(link instanceof SVGAElement ? link.getAttribute('xlink:href') : null) (link instanceof SVGAElement ? link.getAttribute('xlink:href') : null)
if (linkHref == null) return if (linkHref == null) return
const { href, origin, pathname, hash, search } = new URL( const { href, origin, pathname } = new URL(linkHref, link.baseURI)
linkHref, const currentLoc = new URL(location.href) // copy to keep old data
link.baseURI
)
const currentUrl = new URL(location.href) // copy to keep old data
// only intercept inbound html links // only intercept inbound html links
if (origin === currentUrl.origin && treatAsHtml(pathname)) { if (origin === currentLoc.origin && treatAsHtml(pathname)) {
e.preventDefault() e.preventDefault()
if ( go(href, link)
pathname === currentUrl.pathname &&
search === currentUrl.search
) {
// scroll between hash anchors in the same page
// avoid duplicate history entries when the hash is same
if (hash !== currentUrl.hash) {
history.pushState({}, '', href)
// still emit the event so we can listen to it in themes
window.dispatchEvent(
new HashChangeEvent('hashchange', {
oldURL: currentUrl.href,
newURL: href
})
)
}
if (hash) {
// use smooth scroll when clicking on header anchor links
scrollTo(link, hash, link.classList.contains('header-anchor'))
} else {
window.scrollTo(0, 0)
}
} else {
go(href)
}
} }
}, },
{ capture: true } { capture: true }
@ -277,12 +273,12 @@ export function useRoute(): Route {
return useRouter().route return useRouter().route
} }
export function scrollTo(el: Element, hash: string, smooth = false) { export function scrollTo(from: Element | null, hash: string, smooth = false) {
let target: Element | null = null let target: Element | null = null
try { try {
target = el.classList.contains('header-anchor') target = from?.classList.contains('header-anchor')
? el ? from
: document.getElementById(decodeURIComponent(hash).slice(1)) : document.getElementById(decodeURIComponent(hash).slice(1))
} catch (e) { } catch (e) {
console.warn(e) console.warn(e)

Loading…
Cancel
Save