Vue Router 实战

引言

Vue Router 是 Vue.js 的官方路由库,为单页应用(SPA)提供完整的导航和路由管理功能。从 Vue 3 开始,Vue Router 4 带来了 Composition API 支持、更好的 TypeScript 支持以及更灵活的 API 设计。本文将深入讲解 Vue Router 的核心概念和实战技巧。

一、基础配置与安装

1.1 安装

css 复制代码
npm install vue-router@4

1.2 创建路由实例

javascript 复制代码
// router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: { title: '首页' }
  },
  {
    path: '/about',
    name: 'About',
    component: About,
    meta: { title: '关于我们' }
  },
  {
    path: '/user/:id',
    name: 'User',
    component: () => import('../views/User.vue'),
    meta: { title: '用户详情' }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

1.3 在应用中使用

javascript 复制代码
// 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')

二、核心功能实战

2.1 编程式导航

xml 复制代码
<!-- 组件内导航 -->
<template>
  <div>
    <!-- 声明式导航 -->
    <router-link to="/about">关于我们</router-link>
    
    <!-- 编程式导航 -->
    <button @click="goHome">返回首页</button>
    <button @click="goUser(123)">查看用户</button>
    <button @click="goBack">返回</button>
  </div>
</template>

<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'

const router = useRouter()
const route = useRoute()

const goHome = () => {
  router.push('/')
}

const goUser = (id: number) => {
  router.push({
    name: 'User',
    params: { id }
  })
  // 或者
  // router.push(`/user/${id}`)
}

const goBack = () => {
  router.back()
}

// 获取当前路由信息
console.log(route.path)      // 当前路径
console.log(route.params)    // 路由参数
console.log(route.query)     // 查询参数
</script>

2.2 动态路由与参数

arduino 复制代码
// 带参数的路由
{
  path: '/user/:id',
  component: User,
  props: true  // 将 params 作为 props 传递
}

// 在组件中使用
<script setup lang="ts">
import { useRoute } from 'vue-router'

const route = useRoute()
const userId = route.params.id

// 带可选参数
{
  path: '/user/:id?',
  component: User
}

// 带正则验证的参数
{
  path: '/user/:id(\d+)',
  component: User
}

2.3 查询参数

php 复制代码
// 添加查询参数
router.push({
  path: '/search',
  query: { q: 'vue', page: 1 }
})

// 在组件中获取
const searchQuery = route.query.q
const page = route.query.page

三、高级特性

3.1 路由守卫

javascript 复制代码
// 全局前置守卫
router.beforeEach((to, from, next) => {
  const isAuthenticated = localStorage.getItem('token')
  
  if (to.meta.requiresAuth && !isAuthenticated) {
    next({ name: 'Login', query: { redirect: to.fullPath } })
  } else {
    next()
  }
})

// 全局后置守卫
router.afterEach((to, from) => {
  document.title = to.meta.title || '我的应用'
})

// 路由独享守卫
const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      if (isAdmin()) {
        next()
      } else {
        next('/403')
      }
    }
  }
]

// 组件内守卫
<script setup lang="ts">
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'

// 路由更新时调用(参数变化)
onBeforeRouteUpdate((to, from) => {
  // 重新获取数据
  fetchData(to.params.id)
})

// 路由离开前调用
onBeforeRouteLeave((to, from) => {
  if (hasUnsavedChanges()) {
    const confirmed = window.confirm('确定要离开吗?未保存的内容将丢失')
    if (!confirmed) {
      return false
    }
  }
})
</script>

3.2 懒加载

javascript 复制代码
// 路由懒加载
const routes = [
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('../views/Dashboard.vue'),
    meta: { title: '仪表盘' }
  },
  {
    path: '/settings',
    name: 'Settings',
    component: () => import('../views/Settings.vue'),
    meta: { title: '设置' }
  }
]

// 带预加载提示
const routes = [
  {
    path: '/heavy-page',
    component: () => import({
      webpackPrefetch: true,
      webpackChunkName: 'heavy-page'
    }, '../views/HeavyPage.vue')
  }
]

3.3 嵌套路由

javascript 复制代码
const routes = [
  {
    path: '/user',
    component: UserLayout,
    children: [
      {
        path: '',
        redirect: 'profile'
      },
      {
        path: 'profile',
        component: UserProfile,
        name: 'UserProfile'
      },
      {
        path: 'settings',
        component: UserSettings,
        name: 'UserSettings'
      }
    ]
  }
]

// 在父组件中使用
<template>
  <div>
    <h1>用户中心</h1>
    <nav>
      <router-link to="/user/profile">个人资料</router-link>
      <router-link to="/user/settings">设置</router-link>
    </nav>
    <router-view />
  </div>
</template>

3.4 命名视图

ini 复制代码
const routes = [
  {
    path: '/dashboard',
    components: {
      default: DashboardMain,
      sidebar: DashboardSidebar,
      footer: DashboardFooter
    }
  }
]

// 模板中使用
<template>
  <router-view />
  <router-view name="sidebar" />
  <router-view name="footer" />
</template>

四、实战技巧

4.1 路由元信息

vbnet 复制代码
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      requiresAdmin: true,
      title: '管理后台',
      roles: ['admin', 'superadmin']
    }
  }
]

// 在守卫中检查
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
    return
  }
  
  if (to.meta.requiresAdmin && !isAdmin()) {
    next('/403')
    return
  }
  
  next()
})

4.2 滚动行为

typescript 复制代码
const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    // 回到顶部
    if (savedPosition) {
      return savedPosition
    } else {
      return { top: 0 }
    }
  }
})

// 平滑滚动到指定元素
const scrollToElement = (id: string) => {
  const element = document.getElementById(id)
  if (element) {
    element.scrollIntoView({ behavior: 'smooth' })
  }
}

4.3 路由缓存

xml 复制代码
<!-- 使用 keep-alive 缓存路由组件 -->
<template>
  <router-view v-slot="{ Component, route }">
    <keep-alive>
      <component :is="Component" :key="route.name" v-if="$route.meta.keepAlive" />
    </keep-alive>
    <component :is="Component" v-if="!$route.meta.keepAlive" />
  </router-view>
</template>

<script setup lang="ts">
// 组件生命周期钩子
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
  // 组件被激活时调用
  console.log('组件已激活')
})

onDeactivated(() => {
  // 组件被缓存时调用
  console.log('组件已缓存')
})
</script>

五、常见问题与解决方案

5.1 404 处理

arduino 复制代码
const routes = [
  // ... 其他路由
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: NotFound,
    meta: { title: '页面不存在' }
  }
]

5.2 路由重复跳转警告

go 复制代码
// 添加自定义错误处理
const router = createRouter({
  history: createWebHistory(),
  routes
})

// 覆盖默认错误处理
router.onError((error) => {
  if (
    error.message.includes('Avoided redundant navigation') ||
    error.message.includes('Navigation cancelled')
  ) {
    // 忽略重复导航错误
    return
  }
  console.error(error)
})

总结

Vue Router 提供了强大的路由管理能力,从基础的页面导航到复杂的路由守卫、懒加载和嵌套路由。掌握这些核心功能,可以构建出结构清晰、性能优秀的单页应用。

关键要点:

  • 使用路由懒加载优化首屏加载性能
  • 利用路由元信息进行权限控制
  • 合理使用路由守卫保护敏感页面
  • 注意处理路由参数和查询字符串
  • 使用命名视图和嵌套路由组织复杂布局

通过实践这些技巧,你的 Vue 应用将拥有更好的用户体验和可维护性。

相关推荐
哆啦A梦15887 小时前
01, 前端vue3框架的快速搭建以及项目工程的讲解
前端·vue3·springboot
念你那丝微笑7 小时前
2026年Vue前端面试准备
前端·vue.js·面试
冴羽yayujs7 小时前
GitHub 前端热榜项目 - 日榜(2026-05-09)
前端·github
Copy_Paste_Coder7 小时前
小程序失败后,换个方向,终于成功搞到收益
前端·javascript·后端
问心无愧05137 小时前
ctf show web入门31
前端·笔记
ZC跨境爬虫7 小时前
跟着 MDN 学 HTML day_31:(AbortSignal 深入解析与高级中止模式)
前端·ui·html·音视频·视频编解码
UXbot7 小时前
2026年文字转原型AI工具推荐:输入一句需求描述,自动生成多页面可交互界面
前端·低代码·ui·交互·ai编程·原型模式
im_AMBER7 小时前
Browser Agent 开发:从浏览器插件到Electron CDP
前端·javascript·架构·electron·agent
ZC跨境爬虫7 小时前
跟着 MDN 学 HTML day_30:(AbortController 实现可取消的异步请求)
前端·ui·html·edge浏览器·媒体
前端若水7 小时前
选择器的威力 —— :has()、@layer、原生嵌套
前端·css·css3