Migrating from Vue Router
| Feature | Vue Router | Kitbag Router |
|---|---|---|
| Nested routes | ✅ | ✅ |
| Named views | ✅ | ✅ |
| Typed routes | ✅ | ✅ |
| Typed params | 🧪 Experimental | ✅ |
| Navigation guards | ✅ | ✅ |
| Redirects and aliases | ✅ | ✅ |
| Data loaders | ✅ | ✅ |
| Server rendering | ✅ | ✅ |
| View transitions | 🟡 | ✅ |
| Dynamic route registration | ✅ | ❌ |
| Scroll behavior | ✅ | ❌ |
| File-based routing | ✅ | ❌ |
| Rejection views | ❌ | ✅ |
| Async props | ❌ | ✅ |
| Prefetching | ❌ | ✅ |
| Typed external routes | ❌ | ✅ |
See the Quick Start for installation and TypeScript setup.
Route Configuration
Define named routes with createRoute, then attach components with addView. See Routes and Router.
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from './HomeView.vue'
const router = createRouter({
history: createWebHistory(),
routes: [{
name: 'home',
path: '/',
component: HomeView,
}],
})import { createRoute, createRouter } from '@kitbag/router'
import HomeView from './HomeView.vue'
const home = createRoute({
name: 'home',
path: '/',
})
.addView(HomeView)
const router = createRouter([home], {
historyMode: 'browser',
})Child Routes
Use a parent reference instead of children. Kitbag joins paths literally: /users + /[id] becomes /users/[id]. Use hoisting for a child with an independent URL.
const routes = [{
path: '/users',
children: [{
name: 'user',
path: ':id',
component: UserView,
}],
}]const users = createRoute({ path: '/users' })
const user = createRoute({
parent: users,
name: 'user',
path: '/[id]',
})
.addView(UserView)
const routes = [user]Props Binding
Bind props through addView. Kitbag checks them against the component and requires a getter for required props. See Component Props.
const user = {
name: 'user',
path: '/users/:id',
component: UserView,
props: (route) => ({ userId: route.params.id }),
}const user = createRoute({
name: 'user',
path: '/users/[id]',
})
.addView(UserView, {
props: (route) => ({ userId: route.params.id }),
})Named Views
Call addView for each component, with a name for named views. See Named Views.
const home = {
name: 'home',
path: '/',
components: {
default: HomeView,
sidebar: SidebarView,
},
}const home = createRoute({
name: 'home',
path: '/',
})
.addView(HomeView)
.addView(SidebarView, { name: 'sidebar' })Navigation
Pass the route name and params separately. See Navigation.
router.push({
name: 'user',
params: { id: '123' },
})
router.replace({
name: 'user',
params: { id: '456' },
})router.push('user', { id: '123' })
router.replace('user', { id: '456' })Links
Use the resolver callback for typed link destinations. See RouterLink.
<RouterLink :to="{
name: 'user',
params: { id: '123' },
}">
View user
</RouterLink><RouterLink :to="(resolve) => resolve('user', { id: '123' })">
View user
</RouterLink>View Transitions
Vue Router supports view transitions through links. Kitbag also supports router and route defaults, programmatic navigation, transition types, and shared-element helpers. See View Transitions.
<RouterLink to="/about" view-transition>
About
</RouterLink>import { createRoute, createRouter } from '@kitbag/router'
const photo = createRoute({
name: 'photo',
path: '/photos/[id]',
})
const settings = createRoute({
name: 'settings',
path: '/settings',
viewTransition: false,
})
const router = createRouter([photo, settings], {
viewTransition: {
types: ({ to }) => to.name === 'photo' ? ['expand'] : ['fade'],
},
})
// Uses the router's "expand" transition type.
router.push('photo', { id: '1' })
// Adds "slide-left" for this navigation.
router.push('photo', { id: '2' }, { viewTransition: ['slide-left'] })
// The route opts out of transitions.
router.push('settings')Reading the Current Route
Kitbag exposes query values through URLSearchParams and matched routes through matches. Declared query params are also available in route.params. See Router Route.
import { useRoute } from 'vue-router'
const route = useRoute()
const page = route.query.page
const matches = route.matched
const hash = route.hash // '#comments'import { useRoute } from '@kitbag/router'
const route = useRoute()
const page = route.query.get('page')
const matches = route.matches
const hash = route.hash // 'comments'Navigation Guards
Use context helpers to redirect or cancel navigation. The previous route is available as context.from. See Hooks.
const account = {
name: 'account',
path: '/account',
component: AccountView,
beforeEnter: () => {
if (!isSignedIn()) {
return '/login'
}
},
}const account = createRoute({
name: 'account',
path: '/account',
})
.addView(AccountView)
.onBeforeRouteEnter((to, context) => {
if (!isSignedIn()) {
context.replace('/login')
}
})Typed Params
Kitbag parses and validates params using their declared types. Vue Router supports this through its experimental param parsers, which require the experimental router and plugin setup. Both examples expose id as a number for /users/42. See Param Types.
<!-- src/pages/users/[id=int].vue -->
<script setup lang="ts">
const route = useRoute('/users/[id=int]')
route.params.id // 42 (number)
</script>import { createRoute, useRoute, withParams } from '@kitbag/router'
const user = createRoute({
name: 'user',
path: withParams('/users/[id]', {
id: Number,
}),
})
// In the component, after registering the route:
const route = useRoute('user')
route.params.id // 42 (number)Route Regex
Validate params with regular expressions using withParams. See Param Types.
const archive = {
name: 'archive',
path: '/archive/:date(\\d{2}-\\d{2}-\\d{4})',
}import { createRoute, withParams } from '@kitbag/router'
const archive = createRoute({
name: 'archive',
path: withParams('/archive/[date]', {
date: /^\d{2}-\d{2}-\d{4}$/,
}),
})Repeatable Params
Combine a greedy param with arrayOf to read multiple path segments as an array. Both examples match /one/two with chapters ['one', 'two'].
To also match /, use [?chapters*]. Add withDefault for an empty array when the param is missing. See Default Values.
const chapters = {
name: 'chapters',
path: '/:chapters+',
}import { arrayOf, createRoute, withParams } from '@kitbag/router'
const chapters = createRoute({
name: 'chapters',
path: withParams('/[chapters*]', {
chapters: arrayOf([String], { separator: '/' }),
}),
})Redirects
Use redirectTo for a fixed destination and a before hook for conditional redirects. See Redirects.
const routes = [{
name: 'new',
path: '/new',
}, {
name: 'old',
path: '/old',
redirect: { name: 'new' },
}]const newRoute = createRoute({
name: 'new',
path: '/new',
})
const oldRoute = createRoute({
name: 'old',
path: '/old',
})
.redirectTo(newRoute)
const routes = [newRoute, oldRoute]Aliases
Both routers keep the alias URL in the address bar. Kitbag also supports aliases with different params through a transform. See Aliases.
const user = {
name: 'user',
path: '/users/:id',
alias: '/members/:id',
}const user = createRoute({
name: 'user',
path: '/users/[id]',
})
.addAlias({ path: '/members/[id]' })