Vue Router 是 Vue.js 官方的路由管理器,用于构建单页面应用(SPA)。它与 Vue.js 核心深度集成,使得构建单页面应用变得易如反掌。
Vue Router 是 Vue.js 的官方路由管理器,用于处理应用程序中的页面导航。它允许您在不刷新页面的情况下切换视图,创建具有多个"页面"的单页面应用。
在传统的多页面应用中,每个页面都是一个独立的 HTML 文件。而在单页面应用(SPA)中,只有一个 HTML 文件,Vue Router 负责根据 URL 动态切换显示的组件,实现"页面"间的切换。
无需重新加载整个页面,提供类似原生应用的体验
基于组件的路由配置,代码结构更清晰
强大的导航守卫,控制路由访问权限
完整的浏览器历史记录管理
# 使用 npm
npm install vue-router@4
# 使用 yarn
yarn add vue-router@4
# 使用 pnpm
pnpm add vue-router@4
// 1. 导入路由相关函数
import { createRouter, createWebHistory } from 'vue-router'
// 2. 导入路由组件
import Home from './views/Home.vue'
import About from './views/About.vue'
import User from './views/User.vue'
// 3. 定义路由映射
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/user/:id',
name: 'User',
component: User
}
]
// 4. 创建路由实例
const router = createRouter({
// 使用 HTML5 History 模式
history: createWebHistory(),
// 路由配置
routes
})
// 5. 导出路由实例
export default router
// main.js / main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入路由配置
const app = createApp(App)
// 使用路由
app.use(router)
app.mount('#app')
Vue Router 支持两种路由模式:
| 模式 | 创建函数 | URL 示例 | 特点 |
|---|---|---|---|
| Hash 模式 | createWebHashHistory() |
http://example.com/#/about |
兼容性好,无需服务器配置 |
| History 模式 | createWebHistory() |
http://example.com/about |
URL 美观,需要服务器配置支持 |
| Memory 模式 | createMemoryHistory() |
不依赖浏览器 URL | 适用于 Node.js 或非浏览器环境 |
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
// History 模式(推荐)
const router = createRouter({
history: createWebHistory(), // 使用 HTML5 History API
routes: [...]
})
// Hash 模式
const router = createRouter({
history: createWebHashHistory(), // 使用 URL hash
routes: [...]
})
// 带基础路径的 History 模式
const router = createRouter({
history: createWebHistory('/my-app/'), // 指定基础路径
routes: [...]
})
使用 History 模式时,需要确保服务器配置正确,对于所有路径都返回相同的 HTML 文件,否则用户直接访问或刷新页面时会收到 404 错误。
<router-view> 是一个 functional 组件,用于渲染匹配到的路由组件。
<template>
<div id="app">
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link to="/user/123">用户</router-link>
</nav>
<!-- 路由出口 -->
<router-view></router-view>
</div>
</template>
<router-link> 组件用于创建导航链接。
<!-- 基本用法 -->
<router-link to="/about">关于我们</router-link>
<!-- 使用命名路由 -->
<router-link :to="{ name: 'user', params: { id: 123 } }">
用户资料
</router-link>
<!-- 带查询参数 -->
<router-link :to="{ path: '/search', query: { q: 'vue' } }">
搜索 Vue
</router-link>
<!-- 自定义样式类名 -->
<router-link
to="/about"
active-class="router-link-active"
exact-active-class="router-link-exact-active"
>
关于
</router-link>
<!-- 渲染为其他标签 -->
<router-link to="/home" custom v-slot="{ navigate, href, isActive }">
<a :href="href" @click="navigate" :class="{ active: isActive }">
首页
</a>
</router-link>
这是 Vue Router 的演示页面。
动态路由允许我们根据参数动态匹配路由,常用于用户资料、文章详情等场景。
// 路由配置
const routes = [
// 静态路由
{ path: '/', component: Home },
// 动态路由 - 使用冒号标识参数
{ path: '/user/:id', component: User },
// 多个动态参数
{ path: '/user/:id/posts/:postId', component: Post },
// 可选参数
{ path: '/archive/:year?/:month?/:day?', component: Archive },
// 路由正则匹配
{ path: '/user/:id(\\d+)', component: User }, // 只匹配数字ID
// 可重复参数
{ path: '/tags/:tags+', component: Tags },
// 通配符路由(404页面)
{ path: '/:pathMatch(.*)*', component: NotFound }
]
<!-- User.vue 组件 -->
<template>
<div>
<h2>用户资料</h2>
<p>用户ID: {{ userId }}</p>
<p>用户名: {{ userName }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
// 访问动态参数
const userId = route.params.id
// 访问查询参数
const userName = route.query.name || '未知用户'
</script>
<!-- Options API 写法 -->
<script>
export default {
computed: {
userId() {
return this.$route.params.id
},
userName() {
return this.$route.query.name || '未知用户'
}
}
}
</script>
嵌套路由允许在组件内部嵌套其他路由,常用于构建具有布局结构的应用。
const routes = [
{
path: '/dashboard',
component: DashboardLayout,
children: [
{
// 当 /dashboard 时显示 DashboardHome
path: '',
component: DashboardHome
},
{
// 当 /dashboard/profile 时显示 DashboardProfile
path: 'profile',
component: DashboardProfile
},
{
// 当 /dashboard/settings 时显示 DashboardSettings
path: 'settings',
component: DashboardSettings,
children: [
{
// 当 /dashboard/settings/account 时显示 AccountSettings
path: 'account',
component: AccountSettings
},
{
// 当 /dashboard/settings/security 时显示 SecuritySettings
path: 'security',
component: SecuritySettings
}
]
}
]
}
]
<!-- DashboardLayout.vue -->
<template>
<div class="dashboard">
<aside class="sidebar">
<nav>
<router-link to="/dashboard">概览</router-link>
<router-link to="/dashboard/profile">个人资料</router-link>
<router-link to="/dashboard/settings">设置</router-link>
</nav>
</aside>
<main class="content">
<!-- 嵌套路由出口 -->
<router-view></router-view>
</main>
</div>
</template>
<!-- Settings 组件内还可以有嵌套的 router-view -->
<!-- DashboardSettings.vue -->
<template>
<div>
<h3>设置</h3>
<nav>
<router-link to="/dashboard/settings/account">账户设置</router-link>
<router-link to="/dashboard/settings/security">安全设置</router-link>
</nav>
<!-- 二级嵌套路由出口 -->
<router-view></router-view>
</div>
</template>
除了使用 <router-link> 创建声明式导航,我们还可以在 JavaScript 中使用编程式导航。
import { useRouter } from 'vue-router'
const router = useRouter()
// 1. 字符串路径
router.push('/home')
// 2. 带路径的对象
router.push({ path: '/home' })
// 3. 命名路由
router.push({ name: 'user', params: { id: '123' } })
// 4. 带查询参数
router.push({ path: '/search', query: { q: 'vue' } })
// 5. 带 hash
router.push({ path: '/about', hash: '#team' })
// 6. 替换当前路由(不添加历史记录)
router.replace({ path: '/login' })
// 7. 前进/后退
router.go(1) // 前进
router.go(-1) // 后退
// 8. 前进/后退(Vue Router 4 新方法)
router.forward() // 前进
router.back() // 后退
// Options API 中使用 this.$router
export default {
methods: {
goToHome() {
this.$router.push('/home')
},
goBack() {
this.$router.back()
}
}
}
为路由指定名称,可以更方便地进行导航和参数传递。
const routes = [
{
path: '/user/:id',
name: 'user', // 路由名称
component: User
}
]
// 使用命名路由导航
router.push({ name: 'user', params: { id: 123 } })
// 在模板中使用
<router-link :to="{ name: 'user', params: { id: 123 } }">
用户资料
</router-link>
命名视图允许在同一级路由中展示多个视图组件。
<!-- 有多个命名视图 -->
<router-view name="header"></router-view>
<router-view></router-view>
<router-view name="footer"></router-view>
<!-- 路由配置 -->
const routes = [
{
path: '/',
components: {
default: Home, // 默认视图
header: Header, // 命名视图 'header'
footer: Footer // 命名视图 'footer'
}
}
]
路由元信息(meta字段)允许我们在路由配置中添加自定义数据,常用于权限控制、页面标题等。
const routes = [
{
path: '/dashboard',
component: Dashboard,
meta: {
requiresAuth: true, // 需要登录
title: '控制面板', // 页面标题
roles: ['admin', 'user'], // 允许的角色
breadcrumb: '主页' // 面包屑文本
}
},
{
path: '/login',
component: Login,
meta: {
guestOnly: true, // 仅允许未登录用户访问
title: '登录'
}
}
]
// 在组件中访问元信息
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.meta.requiresAuth) // true
// 在导航守卫中访问
router.beforeEach((to, from) => {
const requiresAuth = to.meta.requiresAuth
// ...
})
导航守卫是 Vue Router 提供的钩子函数,用于控制导航的流程。
const router = createRouter({ ... })
// 全局前置守卫
router.beforeEach((to, from, next) => {
// to: 即将要进入的目标路由
// from: 当前导航正要离开的路由
// 检查是否需要登录
if (to.meta.requiresAuth && !isAuthenticated()) {
// 重定向到登录页
next({
path: '/login',
query: { redirect: to.fullPath } // 保存重定向地址
})
} else {
// 继续导航
next()
}
})
// 全局解析守卫
router.beforeResolve((to, from) => {
// 在导航被确认之前调用
})
// 全局后置钩子
router.afterEach((to, from) => {
// 导航完成后调用,可以用于修改页面标题等
document.title = to.meta.title || '我的应用'
})
路由懒加载可以将路由组件分割成不同的代码块,按需加载,提高应用性能。
// 使用动态 import 实现懒加载
const routes = [
{
path: '/',
component: () => import('./views/Home.vue')
},
{
path: '/about',
component: () => import('./views/About.vue')
},
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue'),
// 可以为组件指定 webpackChunkName
component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue')
},
{
path: '/user/:id',
// 带条件的懒加载
component: () => {
if (window.innerWidth > 768) {
return import('./views/UserDesktop.vue')
} else {
return import('./views/UserMobile.vue')
}
}
}
]
Vue Router 是 Vue.js 生态系统中至关重要的部分,它为构建单页面应用提供了强大的路由功能。通过学习 Vue Router,您可以:
Vue Router 与 Vue.js 深度集成,提供了声明式和编程式两种导航方式,使得路由管理变得简单而强大。