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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。