vue-multi-router
v0.1.3
Published
Vue 3 multi router
Downloads
18
Readme
vue-multi-router
Vue 3 Multi Router that allows you to have multiple routers in your application.
Live Demo
🚀 Try the interactive playground
Installation
npm install vue-multi-routerFeatures
- ✅ Multiple Independent Routers - Run multiple Vue Router instances simultaneously in a single app
- ✅ Context-Based Navigation - Each routing context maintains its own navigation history
- ✅ Browser History Integration - Back/forward buttons work across contexts with proper URL updates
- ✅ Session Persistence - Context states persist across page reloads via SessionStorage or other implementations
- ✅ TypeScript Support - Full type definitions included
- ✅ Composable API - Easy-to-use composables for accessing router state
Motivation
Vue Router is designed around a single-router-per-app model. That works well for most applications, but falls short when your UI needs multiple independent navigation areas — each with its own route, history stack, and back/forward behavior.
Think of:
- Dashboard applications with several panels, each displaying a different page
- Desktop-like UIs with floating or tiled windows that navigate independently
- Tabbed interfaces where each tab has its own browsing history
- Multi-pane editors (email clients, admin tools) with a sidebar, list, and detail view that all route separately
Without vue-multi-router you'd have to juggle manual <component :is> switching, duplicate router instances with conflicting URL ownership, or complex query-parameter schemes — all of which break browser history and become hard to maintain.
vue-multi-router solves this by letting you wrap any part of your template in a <MultiRouterContext>. Each context gets its own virtual navigation stack while sharing a single set of route definitions and a single browser URL. The library manages history entries so that the browser back/forward buttons work correctly across every context, and state is persisted through page reloads via SessionStorage.
Basic Usage
1. Create Multi Router
// router.ts
import { createMultiRouter } from 'vue-multi-router'
import { createWebHistory } from 'vue-router'
export const multiRouter = createMultiRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: () => import('./views/Layout.vue'),
children: [
{ path: 'home', component: () => import('./views/Home.vue') },
{ path: 'about', component: () => import('./views/About.vue') },
],
},
],
})2. Install Plugin
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { multiRouter } from './router'
const app = createApp(App)
app.use(multiRouter)
app.mount('#app')3. Define Contexts
<!-- App.vue -->
<template>
<MultiRouterContext type="main" name="main" default>
<RouterView />
</MultiRouterContext>
</template>
<script setup>
import { MultiRouterContext } from 'vue-multi-router'
</script>MultiRouterContext acts as an activator by default — clicking anywhere inside it activates the context. No extra wrapper needed.
4. Create Additional Contexts
<!-- Panels.vue -->
<template>
<div v-for="panel in panels" :key="panel.id">
<MultiRouterContext type="panel" :name="`panel-${panel.id}`" initial-location="/home">
<RouterView />
</MultiRouterContext>
</div>
</template>API Reference
createMultiRouter(options)
Creates a multi-router instance.
Options:
history: RouterHistory- Vue Router history instanceroutes: RouteRecordRaw[]- Route definitions (same as Vue Router)historyOptions?: MultiRouterHistoryManagerOptions- History management options
Route Meta Options
multiRouterRoot: boolean
Marks a route as the root for context rendering. When a context navigates to a nested route, RouterView inside the context will start rendering from the route marked with multiRouterRoot: true, skipping parent routes.
const routes = [
{
path: '/dashboard',
component: DashboardLayout,
children: [
{
path: 'panels',
component: PanelsContainer,
children: [
{
path: 'content',
component: PanelContent,
meta: { multiRouterRoot: true }, // Context renders from here
},
],
},
],
},
]This is useful when contexts are nested inside shared layouts but should render independently from their root component.
<MultiRouterContext>
Component that defines a routing context boundary. By default, it also acts as an activator — clicking inside the context activates it.
Props:
type: string- Context type identifier (for debugging/organization)name: string- Unique context identifierlocation?: string- Force specific location (overrides storage)initial-location?: string- Initial location for new contextshistory-enabled?: boolean- Whether to track in browser history (default:true)default?: boolean- Activate by default if no saved context existsactivator?: boolean- Whether to activate context on mousedown (default:true). Set tofalseto opt out of built-in activation behaviorprevent-class?: string- CSS class that prevents activation on click, useful if you want to prevent activation on click of a button that destroys the context
To disable the built-in activator:
<MultiRouterContext type="panel" name="panel-1" :activator="false">
<!-- manage activation manually -->
</MultiRouterContext><MultiRouterContextActivator>
Standalone wrapper component that activates context on user interaction. Useful for advanced cases where you need fine-grained control over which element triggers activation, separate from the MultiRouterContext boundary.
Props:
prevent-class?: string- CSS class that prevents activation on clickas?: string- HTML element to render as wrapper (default: fragment/div)
useMultiRouter()
Composable for accessing multi-router outside a context.
Returns:
activeContextKey: ComputedRef<string | undefined>- Currently active contextactiveHistoryContextKey: ComputedRef<string | undefined>- Context controlling browser URLsetActive(contextKey: string, updateHistory?: boolean): void- Activate a contexthasContext(contextKey: string): boolean- Check if context exists
useMultiRouterContext()
Composable for use inside a MultiRouterContext.
Returns:
manager: useMultiRouter()- MultiRouter manager instancecontextKey: string- This context's keyisActive: ComputedRef<boolean>- Whether this context is activeisHistoryActive: ComputedRef<boolean>- Whether this context controls browser URLactiveContextKey: ComputedRef<string>- Currently active context keyactiveHistoryContextKey: ComputedRef<string>- Currently active history context keyhistoryEnabled: ComputedRef<boolean>- Whether history is enabled for this contextactivate(updateHistory?: boolean): void- Activate this contextsetActive(contextKey: string, updateHistory?: boolean): void- Activate a contexthasContext(contextKey: string): boolean- Check if context exists
Examples
Cards with Query Parameters
<template>
<div v-for="card in cards" :key="card.id">
<MultiRouterContext
type="card"
:name="`card-${card.id}`"
initial-location="/card/content"
:history-enabled="false"
>
<CardContent @close="removeCard(card.id)" />
</MultiRouterContext>
</div>
</template>Accessing Route in Context
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// Navigate within this context
function goToPage(path) {
router.push(path)
}
// Access query params
const searchQuery = computed(() => route.query.q)
</script>Peer Dependencies
vue: ^3.0.0vue-router: ^4.0.0 || ^5.0.0
License
MIT
Development
Running Playground Locally
# Development mode (hot reload)
npm run play
# Production preview
npm run build:playground
npm run preview:playgroundBuilding
# Build library
npm run build
# Build playground for deployment
npm run build:playgroundTesting & Quality
# Run all checks
npm run check
# Type checking
npm run ts:check
# Linting
npm run lint
# Formatting
npm run formatContributing
Contributions are welcome! Please feel free to submit a Pull Request.
