Skip to content

Commit 2a9fc2a

Browse files
brc-ddzonemeen
andauthored
fix: hashchange should only be triggered for same page navigations (#3768)
Co-authored-by: zonemeen <[email protected]>
1 parent 5f28e74 commit 2a9fc2a

File tree

6 files changed

+41
-30
lines changed

6 files changed

+41
-30
lines changed

Diff for: docs/reference/runtime-api.md

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ interface VitePressData<T = any> {
3838
isDark: Ref<boolean>
3939
dir: Ref<string>
4040
localeIndex: Ref<string>
41+
/**
42+
* Current location hash
43+
*/
44+
hash: Ref<string>
4145
}
4246

4347
interface PageData {

Diff for: src/client/app/data.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import {
66
readonly,
77
ref,
88
shallowRef,
9+
watch,
910
type InjectionKey,
1011
type Ref
1112
} from 'vue'
1213
import {
1314
APPEARANCE_KEY,
1415
createTitle,
16+
inBrowser,
1517
resolveSiteDataByRoute,
1618
type PageData,
1719
type SiteData
@@ -47,6 +49,10 @@ export interface VitePressData<T = any> {
4749
dir: Ref<string>
4850
localeIndex: Ref<string>
4951
isDark: Ref<boolean>
52+
/**
53+
* Current location hash
54+
*/
55+
hash: Ref<string>
5056
}
5157

5258
// site data is a singleton
@@ -82,6 +88,21 @@ export function initData(route: Route): VitePressData {
8288
})
8389
: ref(false)
8490

91+
const hashRef = ref(inBrowser ? location.hash : '')
92+
93+
if (inBrowser) {
94+
window.addEventListener('hashchange', () => {
95+
hashRef.value = location.hash
96+
})
97+
}
98+
99+
watch(
100+
() => route.data,
101+
() => {
102+
hashRef.value = inBrowser ? location.hash : ''
103+
}
104+
)
105+
85106
return {
86107
site,
87108
theme: computed(() => site.value.themeConfig),
@@ -95,7 +116,8 @@ export function initData(route: Route): VitePressData {
95116
description: computed(
96117
() => route.data.description || site.value.description
97118
),
98-
isDark
119+
isDark,
120+
hash: computed(() => hashRef.value)
99121
}
100122
}
101123

Diff for: src/client/app/router.ts

+10-11
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,10 @@ export function createRouter(
6666
async function go(href: string = inBrowser ? location.href : '/') {
6767
href = normalizeHref(href)
6868
if ((await router.onBeforeRouteChange?.(href)) === false) return
69-
if (inBrowser) {
70-
const currentUrl = new URL(location.href)
71-
if (href !== normalizeHref(currentUrl.href)) {
72-
// save scroll position before changing url
73-
history.replaceState({ scrollPosition: window.scrollY }, document.title)
74-
history.pushState(null, '', href)
75-
if (new URL(href, fakeHost).hash !== currentUrl.hash) {
76-
window.dispatchEvent(new Event('hashchange'))
77-
}
78-
}
69+
if (inBrowser && href !== normalizeHref(location.href)) {
70+
// save scroll position before changing url
71+
history.replaceState({ scrollPosition: window.scrollY }, document.title)
72+
history.pushState(null, '', href)
7973
}
8074
await loadPage(href)
8175
await router.onAfterRouteChanged?.(href)
@@ -211,7 +205,12 @@ export function createRouter(
211205
if (hash !== currentUrl.hash) {
212206
history.pushState(null, '', href)
213207
// still emit the event so we can listen to it in themes
214-
window.dispatchEvent(new Event('hashchange'))
208+
window.dispatchEvent(
209+
new HashChangeEvent('hashchange', {
210+
oldURL: currentUrl.href,
211+
newURL: href
212+
})
213+
)
215214
}
216215
if (hash) {
217216
// use smooth scroll when clicking on header anchor links

Diff for: src/client/theme-default/composables/hash.ts

-12
This file was deleted.

Diff for: src/client/theme-default/composables/langs.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { computed } from 'vue'
22
import { ensureStartingSlash } from '../support/utils'
33
import { useData } from './data'
4-
import { hashRef } from './hash'
54

65
export function useLangs({
76
removeCurrent = true,
87
correspondingLink = false
98
} = {}) {
10-
const { site, localeIndex, page, theme } = useData()
9+
const { site, localeIndex, page, theme, hash } = useData()
1110
const currentLang = computed(() => ({
1211
label: site.value.locales[localeIndex.value]?.label,
1312
link:
@@ -29,7 +28,7 @@ export function useLangs({
2928
currentLang.value.link.length - 1
3029
),
3130
!site.value.cleanUrls
32-
) + hashRef.value
31+
) + hash.value
3332
}
3433
)
3534
)

Diff for: src/client/theme-default/composables/sidebar.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
getSidebarGroups
1919
} from '../support/sidebar'
2020
import { useData } from './data'
21-
import { hashRef } from './hash'
2221

2322
export interface SidebarControl {
2423
collapsed: Ref<boolean>
@@ -138,7 +137,7 @@ export function useCloseSidebarOnEscape(
138137
export function useSidebarControl(
139138
item: ComputedRef<DefaultTheme.SidebarItem>
140139
): SidebarControl {
141-
const { page } = useData()
140+
const { page, hash } = useData()
142141

143142
const collapsed = ref(false)
144143

@@ -155,7 +154,7 @@ export function useSidebarControl(
155154
isActiveLink.value = isActive(page.value.relativePath, item.value.link)
156155
}
157156

158-
watch([page, item, hashRef], updateIsActiveLink)
157+
watch([page, item, hash], updateIsActiveLink)
159158
onMounted(updateIsActiveLink)
160159

161160
const hasActiveLink = computed(() => {

0 commit comments

Comments
 (0)