深入浅出 Vue 路由:从基础到进阶全解析

路由是现代前端单页应用(SPA)的核心能力之一,它让我们无需刷新页面就能实现不同视图的切换。Vue Router 作为 Vue 官方的路由管理器,与 Vue.js 深度集成,是构建 Vue 应用的必备工具。本文将从基础到进阶,全面讲解 Vue Router 的核心知识点,帮助你彻底掌握 Vue 路由的使用。

一、Vue Router 基础入门

1. 什么是 Vue Router

Vue Router 是 Vue.js 官方的路由插件,它的核心作用是:

  • 建立 URL 路径与组件之间的映射关系
  • 实现组件的按需加载和页面切换
  • 管理路由的历史记录,模拟浏览器的前进 / 后退功能

2. 安装与基本配置

安装(以 Vue3 + Vue Router4 为例)
复制代码
# npm
npm install vue-router@4

# yarn
yarn add vue-router@4

# pnpm
pnpm add vue-router@4
基本配置步骤
  1. 创建路由文件(src/router/index.js):
javascript 复制代码
// 1. 导入必要的依赖
import { createRouter, createWebHistory } from 'vue-router'
// 导入需要路由的组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'

// 2. 定义路由规则
const routes = [
  {
    path: '/', // URL路径
    name: 'Home', // 路由名称(可选)
    component: Home // 对应组件
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]

// 3. 创建路由实例
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // 路由模式(HTML5 History模式)
  routes // 路由规则
})

// 4. 导出路由实例
export default router
  1. 在 main.js 中注册路由
javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router) // 注册路由插件
app.mount('#app')
  1. 在 App.vue 中添加路由出口
javascript 复制代码
<template>
  <div id="app">
    <!-- 路由链接:相当于a标签,不会刷新页面 -->
    <router-link to="/">首页</router-link>
    <router-link to="/about">关于我们</router-link>
    
    <!-- 路由出口:匹配的组件将渲染在这里 -->
    <router-view></router-view>
  </div>
</template>

3. 核心概念解析

  • router-link :Vue Router 提供的导航组件,替代原生<a>标签,点击时不会触发页面刷新,只会更新 URL 和<router-view>内容
  • router-view:路由出口,所有匹配当前 URL 的组件都会渲染到这个位置
  • 路由模式
    • createWebHistory():HTML5 History 模式(推荐),URL 无#,需要后端配置支持
    • createWebHashHistory():Hash 模式,URL 带#,无需后端配置

二、路由进阶用法

1. 动态路由匹配

用于匹配动态变化的路径(如:用户详情页/user/123):

javascript 复制代码
// 路由规则
{
  path: '/user/:id', // :id为动态参数
  name: 'User',
  component: () => import('../views/User.vue') // 懒加载组件
}

在组件中获取动态参数:

javascript 复制代码
<template>
  <div>用户ID:{{ $route.params.id }}</div>
</template>

<script setup>
// 方式1:使用$route(不推荐,耦合度高)
// 方式2:使用useRoute组合式API(推荐)
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // 获取动态参数id
</script>

2. 嵌套路由

用于实现页面的层级嵌套(如:后台管理系统的侧边栏 + 内容区):

javascript 复制代码
// 路由规则
{
  path: '/dashboard',
  component: () => import('../views/Dashboard.vue'),
  // 嵌套路由规则
  children: [
    {
      path: '', // 默认子路由
      component: () => import('../views/Dashboard/Home.vue')
    },
    {
      path: 'profile', // 等价于 /dashboard/profile
      component: () => import('../views/Dashboard/Profile.vue')
    },
    {
      path: 'settings', // 等价于 /dashboard/settings
      component: () => import('../views/Dashboard/Settings.vue')
    }
  ]
}

在父组件中添加子路由出口:

javascript 复制代码
<!-- Dashboard.vue -->
<template>
  <div class="dashboard">
    <aside>
      <router-link to="/dashboard">首页</router-link>
      <router-link to="/dashboard/profile">个人信息</router-link>
      <router-link to="/dashboard/settings">设置</router-link>
    </aside>
    <main>
      <!-- 子路由出口 -->
      <router-view></router-view>
    </main>
  </div>
</template>

3. 编程式导航

除了使用<router-link>,还可以通过代码实现路由跳转:

javascript 复制代码
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()

// 跳转方式1:通过路径
const goToAbout = () => {
  router.push('/about')
}

// 跳转方式2:通过路由名称(推荐,解耦)
const goToUser = () => {
  router.push({
    name: 'User',
    params: { id: 123 }
  })
}

// 跳转方式3:带查询参数
const goToSearch = () => {
  router.push({
    path: '/search',
    query: { keyword: 'vue' } // URL:/search?keyword=vue
  })
}

// 替换当前路由(不会新增历史记录)
const replaceRoute = () => {
  router.replace('/about')
}

// 前进/后退
const goBack = () => {
  router.go(-1) // 后退一步
}
const goForward = () => {
  router.go(1) // 前进一步
}
</script>

4. 路由守卫

路由守卫用于控制路由的访问权限(如:登录验证、权限校验),分为三类:

(1)全局守卫
javascript 复制代码
// src/router/index.js
// 全局前置守卫:路由跳转前触发
router.beforeEach((to, from, next) => {
  // to:目标路由对象
  // from:当前路由对象
  // next:放行函数(Vue3中已废弃,直接返回true/false或路由对象)
  
  // 示例:登录验证
  const isLogin = localStorage.getItem('token')
  // 未登录且访问的不是登录页,跳转到登录页
  if (!isLogin && to.path !== '/login') {
    return '/login'
  }
  // 已登录且访问登录页,跳转到首页
  if (isLogin && to.path === '/login') {
    return '/'
  }
  // 放行
  return true
})

// 全局后置守卫:路由跳转后触发(无拦截能力)
router.afterEach((to, from) => {
  // 示例:修改页面标题
  document.title = to.meta.title || 'Vue App'
})
(2)路由独享守卫
javascript 复制代码
{
  path: '/admin',
  component: () => import('../views/Admin.vue'),
  // 路由独享守卫
  beforeEnter: (to, from) => {
    // 示例:权限校验
    const role = localStorage.getItem('role')
    if (role !== 'admin') {
      alert('无管理员权限!')
      return false
    }
    return true
  },
  meta: { requiresAuth: true } // 自定义元信息
}
(3)组件内守卫
javascript 复制代码
<script setup>
import { onBeforeRouteEnter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'

// 进入组件前触发(此时组件实例未创建,无法访问this)
onBeforeRouteEnter((to, from) => {
  // 可以通过next传递数据
  return (vm) => {
    // vm是组件实例
    console.log('进入组件', vm)
  }
})

// 路由参数更新时触发(如:/user/123 → /user/456)
onBeforeRouteUpdate((to, from) => {
  console.log('路由参数更新', to.params.id)
})

// 离开组件前触发(可用于确认是否离开)
onBeforeRouteLeave((to, from) => {
  const confirmLeave = confirm('确定要离开吗?')
  if (!confirmLeave) {
    return false // 阻止离开
  }
  return true
})
</script>

5. 路由懒加载

为了优化应用加载性能,我们可以将路由组件按需加载(懒加载):

javascript 复制代码
// 方式1:基本懒加载
{
  path: '/about',
  name: 'About',
  component: () => import('../views/About.vue')
}

// 方式2:懒加载并分组(打包时合并到同一个chunk)
const Home = () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
const About = () => import(/* webpackChunkName: "about" */ '../views/About.vue')

{
  path: '/home',
  component: Home
},
{
  path: '/about',
  component: About
}

三、常见问题与解决方案

1. 刷新页面 404(History 模式)

原因 :History 模式下,刷新页面时浏览器会直接请求后端该路径,后端无对应资源则返回 404。解决方案

  • Nginx 配置: nginx

    复制代码
    location / {
      try_files $uri $uri/ /index.html;
    }
  • Apache 配置: apache

    复制代码
    FallbackResource /index.html

2. 路由参数更新但组件不刷新

原因 :相同路由的参数变化时,组件会被复用,不会重新渲染。解决方案

javascript 复制代码
<script setup>
import { useRoute, watch } from 'vue-router'
const route = useRoute()

// 监听路由参数变化
watch(() => route.params.id, (newId, oldId) => {
  // 重新加载数据
  console.log('ID变化:', newId)
})
</script>

3. 路由重复跳转报错

原因 :重复点击相同路由链接时,Vue Router 会抛出错误。解决方案

javascript 复制代码
// src/router/index.js
// 重写push方法
const originalPush = router.push
router.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

四、Vue2 vs Vue3 路由差异

表格

特性 Vue2 (Vue Router3) Vue3 (Vue Router4)
创建路由 new VueRouter() createRouter()
路由模式 mode: 'history' history: createWebHistory()
组合式 API useRouter() / useRoute()
守卫 next 方法 必须调用 next () 直接返回值(true/false/ 路由对象)
生命周期 beforeRouteEnter 需用 next (vm) 支持 setup 语法糖,onBeforeRouteEnter

总结

  1. 核心基础 :Vue Router 的核心是建立路径与组件的映射,通过<router-link>导航、<router-view>渲染,核心模式有 History 和 Hash 两种。
  2. 进阶能力:动态路由实现参数化匹配,嵌套路由实现层级布局,编程式导航支持代码控制跳转,路由守卫实现权限控制。
  3. 性能优化:路由懒加载能有效减小首屏体积,解决 History 模式刷新 404 需配置后端重定向。

掌握以上知识点,你就能应对绝大多数 Vue 项目中的路由场景。建议结合实际项目多练习,尤其是路由守卫和动态路由的使用,这是面试和实际开发中的高频考点。

相关推荐
陈随易2 小时前
MoonBit访谈:MoonBit开发moonclaw实现“养虾”自由
前端·后端·程序员
汀沿河2 小时前
3 LangChain 1.0 中间件(Middleware)- after_model、after_agent
前端·中间件·langchain
紫金修道2 小时前
【OpenClaw】让openclaw根据需求创造自定义skill记录
前端·javascript·chrome
mengqudoh2 小时前
vue springboot mybatis实现自定义条件检索功能
vue.js·spring boot·mybatis
周杰伦fans2 小时前
Edge浏览器 about:blank 问题修复
前端·数据库·edge
嘉琪0012 小时前
Day6 完整学习包(async/await)——2026 0318
前端·javascript·学习
SameX2 小时前
我做了个本地优先的 iOS 足迹 App,上架后才发现:最难的根本不是地图,而是让轨迹活下来
前端
踩着两条虫2 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(十八):扩展与定制之集成第三方库
前端·vue.js·agent