Vue.jsVue Router介绍

Vue Router 是 Vue.js 官方的路由管理器,用于构建单页面应用(SPA)。它与 Vue.js 核心深度集成,使得构建单页面应用变得易如反掌。

什么是 Vue Router?

Vue Router 是 Vue.js 的官方路由管理器,用于处理应用程序中的页面导航。它允许您在不刷新页面的情况下切换视图,创建具有多个"页面"的单页面应用。

核心特性
  • 嵌套路由映射
  • 动态路由匹配
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 视图过渡效果
  • 细粒度的导航控制
  • HTML5 history 模式或 hash 模式

为什么需要 Vue Router?

在传统的多页面应用中,每个页面都是一个独立的 HTML 文件。而在单页面应用(SPA)中,只有一个 HTML 文件,Vue Router 负责根据 URL 动态切换显示的组件,实现"页面"间的切换。

快速响应

无需重新加载整个页面,提供类似原生应用的体验

代码组织

基于组件的路由配置,代码结构更清晰

导航控制

强大的导航守卫,控制路由访问权限

历史管理

完整的浏览器历史记录管理

安装与配置

安装 Vue Router

安装使用 npm 或 yarn 安装

# 使用 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 模式需要服务器配置

使用 History 模式时,需要确保服务器配置正确,对于所有路径都返回相同的 HTML 文件,否则用户直接访问或刷新页面时会收到 404 错误。

基本用法

路由视图

<router-view> 是一个 functional 组件,用于渲染匹配到的路由组件。

示例App.vue 中使用路由

<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 最佳实践
  • 使用命名路由提高代码可维护性
  • 合理使用路由懒加载优化性能
  • 在导航守卫中统一处理权限验证
  • 使用路由元信息存储页面相关数据
  • 为动态路由参数添加验证逻辑
  • 合理组织路由配置文件结构
  • 使用 History 模式以获得更友好的 URL

总结

Vue Router 是 Vue.js 生态系统中至关重要的部分,它为构建单页面应用提供了强大的路由功能。通过学习 Vue Router,您可以:

  • 创建具有多个"页面"的单页面应用
  • 实现动态路由匹配和参数传递
  • 构建复杂的嵌套路由结构
  • 控制导航流程和权限验证
  • 优化应用性能通过路由懒加载

Vue Router 与 Vue.js 深度集成,提供了声明式和编程式两种导航方式,使得路由管理变得简单而强大。

测试你的理解

思考题
  1. Hash 模式和 History 模式有什么区别?
  2. 如何在组件中获取当前路由的参数?
  3. 什么是路由懒加载?它有什么好处?
  4. 如何使用导航守卫实现权限控制?
  5. 命名路由和命名视图有什么区别?