Legacy Content Notice: This post demonstrates Vue Router 2 patterns from 2016. For modern Vue Router 4 with Vue 3, see our Modern Vue.js Development Guide for updated routing approaches.
Like any other website if the router can not find the URL you're navigating to then you need to display a 404 page to your user for them to know this page doesn't exist anymore. You can redirect any unmatched route to a 404 page in Vue by add the following code snippet to the bottom of your route object.
{ path: '*', component: require('./views/404.vue') }
This will match on all URLs, and display the component for a 404.vue component. This is important that it goes at the bottom of your defined routes, as Vue will go through your URLs and display the first matched component. Therefore placing this at the bottom of the routes object will catch everything that doesn't match a route of your application. This is important to understand when defining dynamic routes for your application too, for example if you have 2 routes like the following.
const router = new VueRouter({
routes: [
{ path: '/blog/:postname', component: Blog },
{ path: '/blog/contact', component: Contact },
]
})
If you were to navigate to /blog/contact URL you would think it will display the Contact component but it will actually display the Blog component with a route.params.postname
of contact. Therefore you need to move static URL to the top of the list to make sure these are matched first.
const router = new VueRouter({
routes: [
{ path: '/blog/contact', component: Contact },
{ path: '/blog/:postname', component: Blog },
]
})
Modern Vue Router 4 Approach
Here's how to handle 404 routes in modern Vue Router 4:
Basic 404 Handling
// router/index.ts
import { createRouter, createWebHistory } from "vue-router";
import type { RouteRecordRaw } from "vue-router";
const routes: RouteRecordRaw[] = [
// Static routes first
{
path: "/blog/contact",
name: "Contact",
component: () => import("@/views/Contact.vue"),
},
// Dynamic routes after static
{
path: "/blog/:postname",
name: "BlogPost",
component: () => import("@/views/Blog.vue"),
props: true,
},
// Catch-all 404 route (must be last)
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: () => import("@/views/404.vue"),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
Advanced 404 with Named Routes
// More specific 404 handling
const routes: RouteRecordRaw[] = [
// Regular routes
{ path: "/", name: "Home", component: Home },
{ path: "/about", name: "About", component: About },
// Blog section with its own 404
{
path: "/blog",
children: [
{ path: "", name: "BlogIndex", component: BlogIndex },
{ path: "contact", name: "BlogContact", component: Contact },
{
path: ":slug",
name: "BlogPost",
component: BlogPost,
props: true,
},
// Blog-specific 404
{
path: ":pathMatch(.*)*",
name: "BlogNotFound",
component: BlogNotFound,
},
],
},
// Global 404 (must be last)
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: NotFound,
},
];
404 Component with Modern Features
<!-- views/404.vue -->
<template>
<div class="not-found">
<h1>404 - Page Not Found</h1>
<p>The page "{{ $route.fullPath }}" could not be found.</p>
<!-- Suggested routes -->
<div v-if="suggestedRoutes.length" class="suggestions">
<h3>Did you mean:</h3>
<ul>
<li v-for="route in suggestedRoutes" :key="route.name">
<router-link :to="route">{{ route.title }}</router-link>
</li>
</ul>
</div>
<router-link to="/" class="home-link"> Go Home </router-link>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { useRoute } from "vue-router";
const route = useRoute();
// Smart suggestions based on current path
const suggestedRoutes = computed(() => {
const currentPath = route.fullPath.toLowerCase();
const suggestions = [];
if (currentPath.includes("blog")) {
suggestions.push({ name: "BlogIndex", title: "Blog Home" });
}
return suggestions;
});
</script>
Key Modern Improvements:
- TypeScript support for route definitions
- Lazy loading with dynamic imports
- Named routes for better maintainability
- Nested routing for complex applications
- Route props for better component isolation
- Composition API with
useRoute
anduseRouter
Related Resources
- Modern Vue.js Development Guide - Complete guide to Vue 3 and Vue Router 4
- Vue Router 4 Documentation - Official Vue Router documentation
- Route Matching Patterns - Modern routing patterns
This post demonstrates Vue Router 2 patterns and is preserved for historical reference. Modern Vue Router 4 provides better TypeScript support, improved pattern matching, and enhanced developer experience.