Vue 3 with Vue Router
In the Vue 3 ecosystem, route management is an indispensable part of developing large-scale Single Page Applications (SPAs). vue-router, as the officially recommended routing plugin, not only provides declarative navigation logic but also integrates deeply with the Composition API, making code organization clearer and more efficient. This article will guide you from scratch on how to integrate and configure vue-router in a Vue 3 project, addressing core requirements such as multi-page routing, dynamic parameter matching, and guard interception.
First, you need to install the necessary dependency packages in the root directory of your project. For projects based on Vite (the recommended build solution for Vue 3), simply execute the following command to get the latest version of Router:
npm install vue-router@latest
yarn add vue-router@latest
pnpm add vue-router@latest
After installation, the core lies in creating a routing configuration instance. In Vue 3, it is recommended to use the createRouter API to initialize the router object, which is more flexible and easier to test than the traditional Vue.use() method. Create a file named router/index.js as the entry point:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{ path: '/', name: 'Home', component: Home },
{
path: '/about/:id',
name: 'AboutDetail',
components: { default: (route) => import(`../views/About/${route.params.id}.vue`) }
}
]
const router = createRouter({
history: createWebHistory(), // Supports HTML5 History Mode, more friendly URLs
routes
})
export default router
This configuration demonstrates two common routing patterns: static paths and dynamic paths with parameters. Here, path defines the matching rules, while name provides a logical name for the route, facilitating programmatic access later on. For handling nested components, Vue Router 3.0+ introduced the <RouteComponent> (i.e., components) attribute to support independent mounting and lifecycle management of child routes.
Next is registering the router with the Vue application instance. Import and enable it in the main.js file:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index' // Ensure correct path
const app = createApp(App)
app.use(router) // Register the router
app.mount('#app')
Once configured, you can achieve declarative navigation through the <RouterLink> component. This component renders as a regular link text but triggers route transitions upon clicking and automatically handles interaction logic such as form submissions:
<template>
<nav class="navbar">
<a router-link to="/">首页</a>
<router-link v-for="item in menuItems" :key="item.name"
:to="{ name: item.path, params: { id } }"
active-class="active">
{{ item.label }}
</router-link>
</nav>
<!-- Page Content -->
<div class="content">
<h1>{{ title }}</h1>
<!-- Conditional rendering: Display corresponding component only when route matches -->
<RouterView />
</div>
</template>
<script setup>
import { RouterLink, RouterView } from 'vue-router'
const menuItems = [
{ name: '/', label: '首页', path: 'home' },
{ name: '/about/:id', label: '详情页', path: 'detail' }
]
// Simulate dynamic parameter passing
const id = Math.floor(Math.random() * 10) + 1
</script>
<RouterView> is the core component of Vue Router; it renders the corresponding child component based on the currently matched route configuration. Combined with the use of <RouteComponent>, you can implement complex nested routing structures, such as loading specific content modules (e.g., article lists, product cards) under a particular ID within a "detail page".
Beyond basic navigation functionality, advanced features are equally important. Route Guards are a key mechanism for controlling application access permissions. Through the beforeEach hook, you can perform logic checks before the user navigates:
router.beforeEach((to, from, next) => {
if (to.name === 'Admin' && !userLoggedIn) {
// If not logged in, redirect to the login page while preserving the original target URL
return next({ name: 'Login', query: { redirect: to.fullPath } })
}
next()
})
Additionally, by utilizing the useRoute and useRouter composable APIs (Composition API), you can directly access the current route state or initiate new navigation requests within a component:
import { useRoute, useRouter } from 'vue-router'
const route = useRoute() // Get information about the currently matched route
const router = useRouter() // Create a router instance for programmatic navigation
// Example: Render different content based on parameters
if (route.params.id === '1') return <Article id="1" />
else if (route.params.id === '2') return <ImageGallery id="2" />
Finally, do not forget to handle error boundaries. When there is a routing configuration error or the URL does not match, vue-router will automatically render the <404> page component (usually named NotFound.vue), ensuring a smooth user experience without interrupting the flow. By reasonably combining static and dynamic routes, nested layouts, and guard logic, you can build an enterprise-level frontend application architecture that is both beautiful and robust.