Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3.5+ Composition API reference with progressive sub-file loading for components, composables, reactivity, and testing.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/router.md
1# Vue Router Typing23Type-safe routing patterns for Vue Router.45> **For Nuxt:** Use file-based routing instead. See `nuxt` skill for Nuxt routing patterns.67## Route Meta Types89Extend `RouteMeta` for typed route.meta:1011```ts12// router/types.ts13import 'vue-router'1415declare module 'vue-router' {16interface RouteMeta {17requiresAuth?: boolean18title?: string19roles?: ('admin' | 'user')[]20}21}22```2324**Usage:**2526```ts27const route = useRoute()28route.meta.requiresAuth // boolean | undefined (typed!)29route.meta.title // string | undefined30```3132## Typed Route Params with unplugin-vue-router3334Use `unplugin-vue-router` for fully typed routes:3536```bash37pnpm add -D unplugin-vue-router38```3940```ts41// vite.config.ts42import VueRouter from 'unplugin-vue-router/vite'4344export default defineConfig({45plugins: [VueRouter(), Vue()], // VueRouter BEFORE Vue46})47```4849**Typed useRoute:**5051```ts52// Auto-generated route types from file structure53const route = useRoute('/users/[id]')54route.params.id // string (typed!)5556const route = useRoute('/posts/[...slug]')57route.params.slug // string[] (typed!)58```5960**Typed router.push:**6162```ts63const router = useRouter()6465// ✅ Type-checked66router.push({ name: '/users/[id]', params: { id: '123' } })6768// ❌ TypeScript error - wrong param69router.push({ name: '/users/[id]', params: { userId: '123' } })70```7172## Scroll Behavior Types7374Type scroll behavior function:7576```ts77import type { RouterScrollBehavior } from 'vue-router'7879const scrollBehavior: RouterScrollBehavior = (to, from, savedPosition) => {80if (savedPosition) return savedPosition81if (to.hash) return { el: to.hash, behavior: 'smooth' }82return { top: 0 }83}8485const router = createRouter({86history: createWebHistory(),87routes,88scrollBehavior,89})90```9192## Dynamic Route Params9394Handle union types for dynamic segments:9596```ts97// routes/[type].vue where type can be 'posts' | 'users' | 'comments'98const route = useRoute()99100// Narrow params type101type ContentType = 'posts' | 'users' | 'comments'102103const type = route.params.type as ContentType104105// Or use route guards106if (route.params.type === 'posts') {107// TypeScript knows type is 'posts'108}109```110111## Navigation Guards Types112113Type navigation guards:114115```ts116import type { NavigationGuardWithThis, RouteLocationNormalized } from 'vue-router'117118const authGuard: NavigationGuardWithThis<undefined> = (to, from) => {119if (to.meta.requiresAuth && !isAuthenticated()) {120return { name: 'login', query: { redirect: to.fullPath } }121}122}123124router.beforeEach(authGuard)125```126127**Per-route guards:**128129```ts130const routes = [131{132path: '/admin',133component: AdminPage,134beforeEnter: (to: RouteLocationNormalized) => {135if (!hasAdminRole()) return { name: 'forbidden' }136},137},138]139```140141## RouteLocation Types142143Common route types:144145```ts146import type {147RouteLocationNormalized, // Resolved route (after navigation)148RouteLocationNormalizedLoaded, // Current route (from useRoute)149RouteLocationRaw, // Input to router.push()150RouteRecordRaw, // Route config definition151} from 'vue-router'152```153154## Common Mistakes155156**Not extending RouteMeta module:**157158```ts159// ❌ Loses type info160route.meta.customField // any161162// ✅ Extend the interface163declare module 'vue-router' {164interface RouteMeta { customField: string }165}166```167168**Assuming params are always strings:**169170```ts171// Catch-all routes have string[] params172const route = useRoute()173174// ❌ May be string[]175const id = route.params.id176177// ✅ Handle both cases178const id = Array.isArray(route.params.id)179? route.params.id[0]180: route.params.id181```182