Displaying a different route
By default, <RouterView> displays the current route. Pass a route prop to display another route location instead, while the URL stays the same:
template
<RouterView :route="someOtherRoute" />The value must be a resolved route location, e.g. the result of router.resolve(). If the route components are lazy loaded, load them first with loadRouteLocation(). When the route prop is undefined, <RouterView> inherits the route provided by the parent view. Only a top-level <RouterView> falls back to the current route from the URL.
Modals with their own URL
The most common use case is a modal that has its own URL, while the page that opened it stays visible in the background. For example, opening the details of a user in a modal goes to /users/1, but the home page is still displayed behind it.
Save the location of the background page in the history state when opening the modal:
ts
router.push({
name: 'user',
params: { id },
state: { backgroundView: router.currentRoute.value.fullPath },
})Then, render the background page with the route prop, and render the modal next to it with a second <RouterView> that displays the current route:
vue
<script setup lang="ts">
import { computed, shallowRef } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const historyState = shallowRef(history.state)
router.afterEach(() => {
historyState.value = history.state
})
const backgroundRoute = computed(() =>
historyState.value?.backgroundView
? router.resolve(historyState.value.backgroundView)
: undefined
)
</script>
<template>
<RouterView :route="backgroundRoute" />
<dialog v-if="backgroundRoute" open>
<RouterView />
<button @click="router.back()">Close</button>
</dialog>
</template>The same route component is displayed in the modal when the user opens it from a page, and as a full page when the user visits /users/1 directly or reloads the page. If the background page uses lazy loaded components, load them before the navigation ends:
ts
router.beforeResolve(async () => {
const { backgroundView } = history.state ?? {}
if (backgroundView) {
await loadRouteLocation(router.resolve(backgroundView))
}
})Reading the route inside the view
Nested <RouterView>s, useRoute(), and the active classes of <RouterLink> inside a <RouterView> with a route prop use that route. This way, the background page and its children behave as if the user was still on that page: their params, query, and watchers do not change when the modal opens.
Some values still use the current route (the URL):
$route, which is the same asuseRouter().currentRoute.value.- Relative locations like
{ query: { tab: 'posts' } }inrouter.push()and<RouterLink>. They are resolved against the current route, not the displayed one.
If a component needs the current route, place it outside of the <RouterView> that receives the route prop, like the modal above, or read useRouter().currentRoute.
WARNING
In v5.4 and earlier, useRoute() and <RouterLink> ignored the route prop and always used the current route. If a component inside the view relies on that, e.g. a modal placed inside the background page that reads the params of the modal route, move it next to the <RouterView>, as shown above.
