Vue Router 核心是解决啥问题的?
p>咱做Vue项目的时候,经常需要在不同页面之间跳转,还得让URL和页面状态对应上,这时候Vue Router就派上大用场了!它是Vue.js官方的路由管理器,专门解决单页应用(SPA)里的页面导航、组件切换这些问题,不管是做个人博客、电商网站还是后台管理系统,搞懂Vue Router能让页面跳转丝滑又省心,接下来咱从基础到实战,把Vue Router的关键知识点和项目里的用法唠明白~
先想明白单页应用(SPA)的特点:整个项目就一个HTML页面,页面切换靠JS动态渲染组件,要是没有路由管理,用户刷新页面就回到初始状态,而且URL也不变,根本分不清当前在哪个“页面”,Vue Router干的事儿就是让URL和组件一一对应,比如访问/home 显示首页组件,访问 /about 显示关于页组件;同时支持无刷新跳转,还能管理路由参数、页面状态。
举个实际场景:做电商APP的商品列表页,点某个商品跳转到详情页,URL变成 /product/123(123是商品ID),这时候Vue Router能帮咱把商品ID从URL里取出来,传给详情组件,还能在用户刷新页面时,让详情页依然显示对应商品信息,要是没有路由,要么页面切换卡成PPT,要么刷新就“失忆”,体验拉胯~
想在Vue项目里用Vue Router,得咋起步?
#### 1. 先把Vue Router装到项目里 Vue2和Vue3对应的Vue Router版本不一样: - Vue2项目 → 装vue-router@3(命令:npm i vue-router@3)
- Vue3项目 → 装 vue-router@4(命令:npm i vue-router@4)
装完后,得在项目里配置路由实例。
配置路由规则(以Vue3 + Vue Router4为例)
新建个 router/index.js 文件,基本结构长这样:
import { createRouter, createWebHistory } from 'vue-router'
// 引入页面组件
import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue'
const router = createRouter({
history: createWebHistory(), // 路由模式:history模式(URL没有#)
routes: [ // 路由规则数组
{
path: '/', // 访问根路径
name: 'home',
component: HomeView // 对应组件
},
{
path: '/about',
name: 'about',
component: AboutView
}
]
})
export default router
然后在 main.js 里把路由挂载到Vue应用:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 引入路由实例
const app = createApp(App)
app.use(router) // 注入路由
app.mount('#app')
让路由“显示”在页面里
在根组件(App.vue)里,用 <router-view> 标签当“容器”,路由匹配到的组件会渲染到这里:
<template>
<div id="app">
<!-- 导航链接 -->
<router-link to="/">首页</router-link>
<router-link to="/about">lt;/router-link>
<!-- 路由组件渲染的地方 -->
<router-view></router-view>
</div>
</template>
<router-link> 是Vue Router提供的导航组件,点击后会触发路由跳转,比自己写 <a> 标签+window.location 优雅多了,还能避免页面刷新~
项目里常见的路由玩法有哪些?
#### 1. 动态路由:页面根据URL参数变化 比如做用户中心,每个用户的详情页URL是/user/1、/user/2… 这里的 1、2 是用户ID,属于**动态参数**,配置路由时,用 :参数名 标记动态段:
```js
routes: [
{
path: '/user/:id', // :id 是动态参数
name: 'user',
component: UserView
}
]
```
在 UserView 组件里,通过 useRoute(Vue3组合式API)或者 this.$route(Vue2选项式API)拿到参数:
```js
// Vue3 组合式API
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
console.log(route.params.id) // 拿到URL里的id
}
}
// Vue2 选项式API export default { mounted() { console.log(this.$route.params.id) } }
场景超常见:电商商品详情、论坛帖子详情、个人主页都得这么玩~
#### 2. 嵌套路由:页面里再套页面
比如后台管理系统, layouts 有侧边栏(SideBar)和主体内容(MainContent),点击侧边栏菜单,主体内容区切换不同页面,这就是**嵌套路由**,配置时用 <code>children</code> 数组:
```js
routes: [
{
path: '/admin',
component: AdminLayout, // 父布局组件
children: [
{
path: 'dashboard', // 注意:子路由path不加/,最终URL是 /admin/dashboard
component: DashboardView
},
{
path: 'settings',
component: SettingsView
}
]
}
]
父组件 AdminLayout.vue 里得有 <router-view> 来渲染子路由组件:
<template>
<div class="admin-layout">
<SideBar /> <!-- 侧边栏组件 -->
<router-view></router-view> <!-- 子路由组件渲染到这 -->
</div>
</template>
这样结构清晰,还能复用布局,后台系统、博客后台这类有层级的页面都靠嵌套路由组织~
路由懒加载:让首屏加载更快
如果项目页面多,把所有组件都打包到一个JS文件里,首屏加载会很慢。路由懒加载就是让组件在需要的时候再加载(比如用户访问到某个路由时才加载对应的组件),配置时把 component 改成函数式导入:
routes: [
{
path: '/about',
component: () => import('../views/AboutView.vue') // 懒加载,访问/about时才加载组件
}
]
这样打包后,每个路由组件会生成单独的JS块,首屏只加载必要的代码,用户等的时间更短,体验更爽~
编程式导航:用JS控制跳转
除了 <router-link> 点击跳转,有时候需要在代码里触发跳转(比如登录成功后跳转到首页),这时候用编程式导航,Vue Router提供了 router.push、router.replace 这些方法:
// Vue3 组合式API(先引入useRouter)
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
const handleLogin = () => {
// 登录逻辑...
router.push('/home') // 跳转到首页
}
return { handleLogin }
}
}
// Vue2 选项式API
export default {
methods: {
handleLogin() {
// 登录逻辑...
this.$router.push('/home')
}
}
}
router.push 会往历史记录里添加新记录,router.replace 是替换当前记录(比如支付成功后替换成结果页,用户返回不会回到支付页),router.go(1) 类似浏览器的前进,router.go(-1) 是后退~
路由守卫是干啥的?项目里咋用?
路由守卫就像“门卫”,在路由跳转的**前、中、后**插手,做权限判断、加载数据、修改页面标题这些事儿。全局守卫:控制所有路由跳转
最常用的是 router.beforeEach,每次路由跳转前都会触发,比如后台系统,进入 /admin 前检查用户是否登录:
// router/index.js 里配置
router.beforeEach((to, from, next) => {
const isLogin = localStorage.getItem('token') // 假设用token判断登录
if (to.path.startsWith('/admin') && !isLogin) {
next('/login') // 没登录,跳转到登录页
} else {
next() // 放行
}
})
to 是要跳转到的目标路由,from 是当前离开的路由,next 是必须调用的函数(放行、跳转、取消都靠它)。
路由独享守卫:只管单个路由
在路由配置里写 beforeEnter,比如某个敏感页面,除了全局权限,还要额外校验:
routes: [
{
path: '/secret',
component: SecretView,
beforeEnter: (to, from, next) => {
const hasPermission = checkPermission() // 自定义权限检查函数
if (hasPermission) {
next()
} else {
next('/403') // 没权限跳403页面
}
}
}
]
组件内守卫:组件自己管自己
在组件里写 beforeRouteEnter(进入前)、beforeRouteUpdate(路由参数变化但组件复用)、beforeRouteLeave(离开前),比如编辑表单页面,离开前提醒用户保存:
// Vue2 选项式API
export default {
beforeRouteLeave(to, from, next) {
if (this.formEdited) { // 假设formEdited标记表单是否修改
const confirm = window.confirm('表单没保存,确定离开吗?')
if (confirm) {
next()
} else {
next(false) // 取消跳转
}
} else {
next()
}
}
}
// Vue3 组合式API(用onBeforeRouteLeave)
import { onBeforeRouteLeave } from 'vue-router'
export default {
setup() {
onBeforeRouteLeave((to, from, next) => {
// 逻辑和上面类似
next()
})
}
}
组件内守卫很灵活,适合处理组件自身的状态和逻辑~
遇到路由相关的 bug,咋排查?
项目里路由出问题,常见场景和解决方法总结几个典型的:404页面不生效
想配个404页面,结果访问不存在的路由还是白屏?原因:路由配置的顺序不对,404的路由得放在最后(因为路由匹配是从上到下,一旦前面匹配到就不会往后走),正确配置:
routes: [
{ path: '/home', component: HomeView },
{ path: '/about', component: AboutView },
// 其他路由...
{ path: '/:pathMatch(.*)*', component: Error404View } // 匹配所有未定义的路由
]
刷新页面后路由“崩了”(history模式)
用 createWebHistory(Vue3)或 mode: 'history'(Vue2)时,刷新页面报404?原因:history模式下,URL没有,后端不知道 /user/123 对应的是前端路由,所以返回404。解决:让后端配置“所有请求都返回index.html”,把路由控制权交回前端,比如Nginx配置:
location / {
try_files $uri $uri/ /index.html;
}
路由参数变了,组件没更新
比如从 /user/1 跳转到 /user/2,组件还是显示用户1的信息?原因:Vue Router发现组件是同一个,不会重新渲染,所以数据没更新。解决:
- 用
watch监听路由参数变化:// Vue3 组合式API import { watch, useRoute } from 'vue-router' setup() { const route = useRoute() watch(() => route.params.id, (newId) => { // 根据newId重新请求数据 }) } - 用组件内守卫
beforeRouteUpdate:// Vue2 选项式API beforeRouteUpdate(to, from, next) { this.fetchData(to.params.id) // 重新请求数据 next() }
嵌套路由不显示子组件
配置了children路由,但子组件就是不渲染?原因:父组件里没放 <router-view>,子路由不知道该渲染到哪。解决:在父组件模板里加上 <router-view>,AdminLayout.vue 必须有这个标签才能显示子路由组件~
Vue2和Vue3的Vue Router有啥不一样?
很多同学升级Vue3后,发现路由配置报错,因为Vue Router v4(对应Vue3)和v3(对应Vue2)变化挺大:路由创建方式
-
Vue2 + vue-router@3:
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const router = new VueRouter({ mode: 'history', routes: [...] }) -
Vue3 + vue-router@4:
import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(), // 代替mode: 'history' routes: [...] }) // 不需要Vue.use,直接app.use(router)
组合式API的支持
Vue3里可以用 useRouter、useRoute 在setup里获取路由实例和当前路由:
import { useRouter, useRoute } from 'vue-router'
export default {
setup() {
const router = useRouter()
const route = useRoute()
// 不用this,更简洁
}
}
导航失败的处理
Vue3中,router.push 返回的是Promise,如果导航被取消(比如重复跳转同一个路由),会抛出错误,可以用 try...catch 捕获:
const router = useRouter()
async function goToPage() {
try {
await router.push('/same-page')
} catch (error) {
if (isNavigationFailure(error, NavigationFailureType.aborted)) {
// 导航被取消,做提示
}
}
}
路由实例的挂载
Vue2是在Vue构造函数上挂载路由,Vue3是通过 app.use(router) 挂载到应用实例,更贴合组合式API的设计~
Vue Router是Vue项目里管理页面导航的核心工具,从基础配置到动态路由、嵌套路由、守卫这些进阶玩法,再到版本差异和bug排查,把这些搞透了,做SPA项目就更顺手,实际项目里多练,比如搭个小后台系统,用嵌套路由组织布局,用动态路由做用户管理,用路由守卫做权限控制,很快就能掌握精髓~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网

