From 8e38b1069b7e328fe9b860801ed222a1dd38e55f Mon Sep 17 00:00:00 2001 From: T <6601329+cookesan@users.noreply.github.com> Date: Mon, 29 Jun 2026 02:11:09 -0300 Subject: [PATCH] docs: explain router route-change handlers (#5253) --- docs/en/guide/custom-theme.md | 18 ++++++++++++++++++ docs/en/reference/runtime-api.md | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/en/guide/custom-theme.md b/docs/en/guide/custom-theme.md index c0ce85971..8de4c7ab2 100644 --- a/docs/en/guide/custom-theme.md +++ b/docs/en/guide/custom-theme.md @@ -67,6 +67,24 @@ export default { } ``` +The `router` value is the same VitePress router instance returned by [`useRouter()`](../reference/runtime-api#userouter). To listen for route changes, assign handlers on the router: + +```ts [.vitepress/theme/index.ts] +export default { + enhanceApp({ router }) { + router.onBeforeRouteChange = (to) => { + console.log('navigating to', to) + } + + router.onAfterRouteChange = (to) => { + console.log('navigated to', to) + } + } +} +``` + +Return `false` from `onBeforeRouteChange` or `onBeforePageLoad` to cancel navigation. + The default export is the only contract for a custom theme, and only the `Layout` property is required. So technically, a VitePress theme can be as simple as a single Vue component. Inside your layout component, it works just like a normal Vite + Vue 3 application. Do note the theme also needs to be [SSR-compatible](./ssr-compat). diff --git a/docs/en/reference/runtime-api.md b/docs/en/reference/runtime-api.md index b39e4dcd6..a202b2703 100644 --- a/docs/en/reference/runtime-api.md +++ b/docs/en/reference/runtime-api.md @@ -124,6 +124,18 @@ interface Router { } ``` +Assign route-change handlers on the router instance: + +```ts +const router = useRouter() + +router.onBeforeRouteChange = (to) => { + console.log('navigating to', to) +} +``` + +For custom themes, the same router is available from [`enhanceApp`](../guide/custom-theme#theme-interface). + ## `withBase` - **Type**: `(path: string) => string`