Vue3 路由完全指南:从入门到实战,新手也能快速上手
在 Vue3 项目开发中,路由(Vue Router)是不可或缺的核心模块——它负责管理页面之间的跳转、实现组件的按需加载、处理路由参数传递,甚至控制页面权限。
很多刚接触 Vue3 的新手,在使用路由时总会遇到各种问题:Vue3 路由和 Vue2 有哪些区别?如何配置路由?嵌套路由怎么实现?路由守卫该怎么用?
今天这篇文章,就带你从零吃透 Vue3 + Vue Router 4(路由最新版本)的使用,从环境搭建、基础配置到进阶技巧、实战案例,每一步都有清晰示例,帮你避开坑点,快速运用到实际项目中。
一、前言:Vue3 路由的核心变化
首先明确一个重点:Vue3 必须搭配Vue Router 4.x 版本(以下简称 Vue Router),它和 Vue2 对应的 Vue Router 3.x 有一些核心差异,新手无需深究底层,但要记住这几点关键变化:
- 不再支持
new VueRouter(),改用createRouter()工厂函数创建路由实例,更贴合 Vue3 的组合式 API 风格。 - 路由模式的配置方式变化,
mode: 'history'改为history: createWebHistory()。 - 支持组合式 API 用法,新增
useRouter()、useRoute()等钩子,替代 Vue2 中的this.$router、this.$route。 - 移除了
router-link的tag属性,改用custom+ 插槽实现自定义标签。
接下来,我们从环境搭建开始,一步步实现 Vue3 路由的各种用法。
二、环境搭建:安装 Vue Router 4
首先确保你已经创建了 Vue3 项目(推荐使用 Vite 创建,效率更高),如果还没有创建,先执行以下命令:
// 创建 Vue3 项目(Vite)
npm create vite@latest vue3-router-demo -- --template vue
cd vue3-router-demo
npm install
// 安装 Vue Router 4(核心步骤)
npm install vue-router@4
安装完成后,我们就可以开始配置路由了。
三、基础配置:实现简单的页面跳转
Vue3 路由的配置核心分为 3 步:创建路由实例 → 定义路由规则 → 在入口文件挂载路由,下面我们一步步操作。
1. 新建路由配置文件
在项目的 src 目录下,新建 router 文件夹,然后创建 index.js 文件(路由的核心配置文件),写入以下代码:
// src/router/index.js
// 1. 引入必要的依赖
import { createRouter, createWebHistory } from 'vue-router'
// 2. 引入需要跳转的组件(页面级组件)
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 3. 定义路由规则(数组形式,每一个对象对应一个路由)
const routes = [
{
path: '/', // 路由路径(URL 中显示的路径)
name: 'Home', // 路由名称(可选,用于编程式导航)
component: Home // 路由对应的组件
},
{
path: '/about',
name: 'About',
component: About
// 也可以使用懒加载(推荐,优化性能)
// component: () => import('../views/About.vue')
}
]
// 4. 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), // 路由模式(history 模式)
routes // 传入路由规则(等同于 routes: routes)
})
// 5. 导出路由实例(供入口文件挂载)
export default router
2. 挂载路由到 Vue 实例
打开项目入口文件 src/main.js,引入路由实例,并用 use() 方法挂载,代码如下:
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
// 引入路由实例
import router from './router'
// 创建 App 实例,并挂载路由
createApp(App)
.use(router) // 挂载路由
.mount('#app')
3. 新建页面组件
在 src 目录下,新建 views 文件夹(用于存放页面级组件),分别创建 Home.vue 和 About.vue 两个组件:
// src/views/Home.vue
<template>
<div class="home">
<h1>首页</h1>
<p>这是 Vue3 路由的首页页面</p>
</div>
</template>
// src/views/About.vue
<template>
<div class="about">
<h1>关于我们</h1>
<p>这是 Vue3 路由的关于页面</p>
</div>
</template>
4. 使用 router-link 和 router-view
路由挂载完成后,需要在App.vue 中使用两个核心组件:
<router-link>:用于实现路由跳转(类似 a 标签,但不会刷新页面),默认渲染为 a 标签。<router-view>:用于渲染当前路由对应的组件(页面内容会显示在这里)。
修改 App.vue 代码:
// src/App.vue
<template>
<div id="app">
<!-- 路由导航:跳转按钮 -->
<nav>
<router-link to="/">首页</router-link> |
<router-link to="/about">关于我们</router-link>
</nav>
<!-- 路由视图:渲染当前路由对应的组件 -->
<router-view />
</div>
</template>
<style>
/* 激活路由的样式(默认类名:router-link-active) */
.router-link-active {
color: #42b983;
text-decoration: none;
font-weight: bold;
}
</style>
5. 运行测试
执行 npm run dev 启动项目,访问本地地址,点击“首页”和“关于我们”,就能实现页面无刷新跳转,并且激活的路由会显示对应样式——这就是 Vue3 路由的基础用法!
补充:路由懒加载(推荐优化)
上面的配置中,我们直接引入了 Home 和 About 组件,这种方式会在项目打包时,将所有页面组件打包到一个文件中,导致文件体积过大,影响首屏加载速度。
推荐使用路由懒加载(按需加载),只有当用户访问该路由时,才会加载对应的组件,优化首屏性能,修改路由规则如下:
// src/router/index.js
const routes = [
{
path: '/',
name: 'Home',
// 懒加载写法:箭头函数 + import()
component: () => import('../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
}
]
四、核心用法:路由参数传递
开发中经常需要在页面跳转时传递参数(比如详情页需要接收列表页的 ID),Vue3 路由支持两种常用的参数传递方式:动态路由参数和查询参数。
1. 动态路由参数(推荐,用于传递必填参数)
动态路由参数是将参数嵌入到路由路径中,格式为 path: '/xxx/:参数名',适用于详情页、编辑页等需要唯一标识的场景。
步骤 1:配置动态路由
// src/router/index.js
// 引入详情页组件
const routes = [
// 其他路由...
{
// 动态路由:id 是参数名(可自定义)
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue')
}
]
步骤 2:跳转时传递参数
有两种跳转方式(声明式导航 + 编程式导航),分别对应参数传递:
// 1. 声明式导航(router-link):直接在 to 中拼接参数
<router-link to="/user/123">用户123</router-link>
// 或者用对象形式(推荐,更灵活)
<router-link :to="{ name: 'User', params: { id: 123 } }">用户123</router-link>
// 2. 编程式导航(useRouter):通过 push 方法传递
<script setup>
// 引入 useRouter 钩子(组合式 API)
import { useRouter } from 'vue-router'
const router = useRouter()
// 跳转并传递参数
const goToUser = () => {
router.push({
name: 'User', // 必须用 name 匹配,不能用 path(path 需手动拼接参数)
params: { id: 123 }
})
}
</script>
步骤 3:接收动态路由参数
在目标组件(User.vue)中,使用 useRoute() 钩子获取路由信息,进而获取参数:
// src/views/User.vue
<template>
<div class="user">
<h1>用户详情页</h1>
<p>用户 ID:{{ $route.params.id }}</p>
<!-- 或者用组合式 API(推荐) -->
<p>用户 ID:{{ route.params.id }}</p>
</div>
</template>
<script setup>
// 引入 useRoute 钩子,获取当前路由信息
import { useRoute } from 'vue-router'
const route = useRoute()
// 打印参数(可在生命周期或方法中使用)
console.log(route.params.id) // 输出:123
</script>
2. 查询参数(用于传递可选参数)
查询参数类似 GET 请求的参数,格式为path?key=value&key2=value2,适用于筛选、搜索等可选参数场景,不需要修改路由配置。
步骤 1:跳转时传递查询参数
// 1. 声明式导航
<router-link to="/search?keyword=vue3&page=1">搜索 Vue3</router-link>
// 或者用对象形式(推荐)
<router-link :to="{
path: '/search',
query: { keyword: 'vue3', page: 1 }
}">搜索 Vue3</router-link>
// 2. 编程式导航
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goToSearch = () => {
router.push({
path: '/search',
query: { keyword: 'vue3', page: 1 }
})
}
</script>
步骤 2:接收查询参数
接收方式和动态路由参数类似,通过 route.query 获取:
// src/views/Search.vue
<template>
<div class="search">
<h1>搜索页</h1>
<p>搜索关键词:{{ route.query.keyword }}</p>
<p>当前页码:{{ route.query.page }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query) // 输出:{ keyword: 'vue3', page: '1' }
</script>
两种参数的区别(重点)
| 参数类型 | URL 显示 | 是否需要配置路由 | 页面刷新后是否保留 | 适用场景 |
|---|---|---|---|---|
| 动态路由参数 | /user/123(嵌入路径) | 是(需配置 :id) | 是 | 必填参数(详情页 ID) |
| 查询参数 | /search?keyword=vue3(拼接在路径后) | 否 | 是 | 可选参数(筛选、搜索) |
五、进阶用法:嵌套路由、路由守卫
掌握基础用法后,我们来看两个开发中高频使用的进阶技巧:嵌套路由和路由守卫。
1. 嵌套路由(多级路由)
嵌套路由用于实现页面的多级导航(比如首页下有“推荐”“热门”两个子页面),核心是在父路由中添加 children数组,配置子路由规则。
示例:实现首页嵌套子路由
// src/router/index.js
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
// 子路由(嵌套路由)
children: [
{
path: '', // 子路由默认路径(访问 / 时,默认显示该子组件)
name: 'HomeRecommend',
component: () => import('../views/HomeRecommend.vue')
},
{
path: 'hot', // 子路由路径(完整路径:/hot)
name: 'HomeHot',
component: () => import('../views/HomeHot.vue')
}
]
}
]
然后在父组件(Home.vue)中,添加 <router-view> 渲染子路由组件:
// src/views/Home.vue
<template>
<div class="home">
<h1>首页</h1>
<!-- 子路由导航 -->
<div class="sub-nav">
<router-link to="/">推荐</router-link> |
<router-link to="/hot">热门</router-link>
</div>
<!-- 子路由视图:渲染子路由对应的组件 -->
<router-view />
</div>
</template>
此时访问 /,会显示 Home 组件 + HomeRecommend 组件;访问 /hot,会显示 Home 组件 + HomeHot 组件,实现多级导航。
2. 路由守卫(路由拦截)
路由守卫用于在路由跳转前、跳转后执行一些逻辑(比如权限判断、页面埋点、取消请求),Vue Router 4 支持 3 种常用守卫:全局守卫、路由独享守卫、组件内守卫。
(1)全局守卫(影响所有路由)
在路由配置文件中定义,适用于全局权限控制(比如未登录禁止访问个人中心):
// src/router/index.js
const router = createRouter({ ... })
// 1. 全局前置守卫(跳转前执行,最常用)
router.beforeEach((to, from, next) => {
// to:即将跳转的路由信息
// from:当前要离开的路由信息
// next():放行;next('/login'):强制跳转;next(false):取消跳转
// 示例:未登录禁止访问 /user
const isLogin = localStorage.getItem('token') // 模拟登录状态
if (to.path === '/user' && !isLogin) {
// 未登录,强制跳转到登录页
next('/login')
} else {
// 已登录,放行
next()
}
})
// 2. 全局后置守卫(跳转后执行,用于埋点、修改页面标题)
router.afterEach((to, from) => {
// 修改页面标题
document.title = to.name || 'Vue3 路由演示'
// 页面埋点(示例)
console.log(`跳转至:${to.path}`)
})
export default router
(2)组件内守卫(影响当前组件)
在组件内部定义,适用于当前组件的路由拦截(比如离开组件时提示保存),Vue3 组合式 API 中使用onBeforeRouteEnter、onBeforeRouteLeave 等钩子:
// src/views/Edit.vue(编辑页)
<script setup>
import { onBeforeRouteLeave } from 'vue-router'
// 组件内守卫:离开当前组件时执行
onBeforeRouteLeave((to, from, next) => {
// 示例:提示用户保存内容
const isSave = confirm('内容未保存,确定要离开吗?')
if (isSave) {
next() // 确认离开,放行
} else {
next(false) // 取消离开
}
})
</script>
六、实战案例:实现登录跳转+权限控制
结合上面的知识点,我们实现一个常见的实战场景:未登录用户访问个人中心时,自动跳转到登录页,登录成功后跳转回个人中心。
1. 配置路由
// src/router/index.js
const routes = [
{ path: '/', component: () => import('../views/Home.vue') },
{ path: '/login', name: 'Login', component: () => import('../views/Login.vue') },
{
path: '/user',
name: 'User',
component: () => import('../views/User.vue'),
meta: { requiresAuth: true } // 标记该路由需要登录权限
}
]
// 全局前置守卫:权限控制
router.beforeEach((to, from, next) => {
// 判断当前路由是否需要登录
if (to.meta.requiresAuth) {
const token = localStorage.getItem('token')
if (token) {
// 已登录,放行
next()
} else {
// 未登录,跳转到登录页,并记录当前路由(登录后跳转回来)
next({ name: 'Login', query: { redirect: to.path } })
}
} else {
// 不需要登录,放行
next()
}
})
2. 登录组件(Login.vue)
// src/views/Login.vue
<template>
<div class="login">
<h1>登录页</h1>
<button @click="login">模拟登录</button>
</div>
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const login = () => {
// 模拟登录:存储 token
localStorage.setItem('token', 'vue3-router-demo-token')
// 获取登录前的跳转路径(如果有,就跳回去;没有就跳首页)
const redirect = route.query.redirect || '/'
router.push(redirect)
}
</script>
3. 个人中心组件(User.vue)
// src/views/User.vue
<template>
<div class="user">
<h1>个人中心</h1>
<button @click="logout">退出登录</button>
</div>
</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const logout = () => {
// 模拟退出:清除 token
localStorage.removeItem('token')
// 跳转到登录页
router.push('/login')
}
</script>
测试流程:访问 /user → 未登录,自动跳转到 /login?redirect=/user → 点击登录 → 跳回 /user → 点击退出登录 → 跳回 /login,完美实现权限控制!
七、避坑指南(新手必看)
- Vue3 必须使用 Vue Router 4.x,不能使用 3.x 版本,否则会报错(版本不兼容)。
- 组合式 API 中,不要在
<script setup>中使用this.$router、this.$route,必须用useRouter()、useRoute()钩子。 - 动态路由参数跳转时,用
name匹配路由,不要用path(用 path 会导致 params 参数失效)。 - 路由懒加载时,组件路径不要写错(相对路径要正确,比如
../views/Home.vue,不要写成./views/Home.vue)。 - 嵌套路由的子路由
path不要加/,否则会被当作根路由(比如子路由 path 写'hot',不要写'/hot')。 - 全局前置守卫中,必须调用
next()、next('/xxx')或next(false),否则路由会卡住,无法跳转。
八、总结
Vue3 + Vue Router 4 的核心用法其实并不复杂,关键是掌握以下几点:
- 基础配置:
createRouter()创建实例 → 挂载到 Vue 实例 → 用router-link和router-view实现跳转和渲染。 - 参数传递:动态路由参数(必填)和查询参数(可选),接收用
route.params和route.query。 - 进阶技巧:嵌套路由用
children配置,权限控制用全局前置守卫。 - 性能优化:路由懒加载按需加载组件,提升首屏速度。
本文涵盖了 Vue3 路由的所有高频用法,从基础到实战,每一步都有清晰示例,新手可以跟着步骤一步步操作,很快就能上手。