vue-router 基础配置要做哪些事?
不少刚开始用Vue做项目的同学,一碰到路由配置、跳转、权限控制这些需求,就被vue-router API的各种用法搞晕,这篇文章用问答形式,把vue-router核心API的用法、场景和实战技巧拆明白,从基础配置到进阶玩法一次讲透~
要让vue-router在项目里跑起来,得完成「安装→创建路由实例→配置路由规则→注入Vue」这几步。先装依赖:Vue2项目用 npm i vue-router@3
,Vue3项目用 npm i vue-router@4
。
然后创建路由实例:
-
Vue2 写法:
import Vue from 'vue' import VueRouter from 'vue-router' import Home from './views/Home.vue' Vue.use(VueRouter) // 全局注册路由插件 const routes = [ { path: '/', component: Home }, { path: '/about', component: () => import('./views/About.vue') } // 懒加载组件 ] const router = new VueRouter({ mode: 'history', // 选择history或hash模式(hash模式用'hash') routes }) export default router
-
Vue3 写法:
import { createRouter, createWebHistory } from 'vue-router' import Home from './views/Home.vue' const routes = [ { path: '/', component: Home }, { path: '/about', component: () => import('./views/About.vue') } ] const router = createRouter({ history: createWebHistory(), // history模式(hash模式用createWebHashHistory) routes }) export default router
最后在入口文件(main.js)里注入:Vue2是 new Vue({ router, ... }).$mount('#app')
;Vue3是 app.use(router).mount('#app')
。
配置路由规则时,path
是访问路径,component
对应渲染的组件,还能加 name
(命名路由,跳转更稳定)、meta
(元信息,存权限、标题等自定义数据)等字段。
路由跳转有几种方式?代码咋写?
路由跳转分「声明式」和「编程式」两种,场景不同选不同方式~
声明式:用 <router-link>
组件
在模板里写,适合页面上的导航按钮、菜单等场景,比如跳转到命名路由并传参:
<router-link :to="{ name: 'User', params: { id: 123 }}">去用户页</router-link>
也能传query参数(参数会拼在URL后,如 ?keyword=vue
):
<router-link :to="{ path: '/search', query: { keyword: 'vue' }}">搜索Vue</router-link>
编程式:用 router 的方法
在JS里调用,适合按钮点击、逻辑判断后跳转等场景,常见方法有 push
、replace
、go
。
-
Vue2 里,组件内通过
this.$router
调用:methods: { goAbout() { this.$router.push('/about') // 直接传路径 this.$router.push({ name: 'About', params: { tab: 'info' }}) // 命名路由+参数 } }
-
Vue3 里,要用
useRouter
钩子拿到router实例:import { useRouter } from 'vue-router' setup() { const router = useRouter() const goUser = () => { router.push({ name: 'User', params: { id: '456' }}) } return { goUser } }
几个方法区别:
push
:新增一条历史记录,点击返回能回到上一页;replace
:替换当前历史记录,点击返回不会回到当前页;go
:类似history.go(n)
,router.go(-1)
是返回上一页。
动态路由参数咋处理?匹配和传参要注意啥?
动态路由用来匹配「路径里带变量」的场景(比如用户页 /user/1
、/user/2
共用一个User组件)。
配置动态路由
在路由规则里加动态段(以 开头),
{ path: '/user/:id', name: 'User', component: User }
这里的 :id
就是动态参数,页面刷新后参数还在(因为参数在URL里)。
组件内获取参数
- Vue2 里,用
this.$route.params.id
(注意是$route
不是$router
,$route
是当前路由信息对象); - Vue3 里,用
useRoute
钩子:import { useRoute } from 'vue-router' setup() { const route = useRoute() console.log(route.params.id) // 拿到动态参数 }
注意!参数变化时组件不刷新
当从 /user/1
跳到 /user/2
,User组件会复用(性能优化),但组件的生命周期钩子(比如created
)不会再执行,这时候要监听参数变化:
-
用
watch
监听$route
(Vue2)或route
(Vue3):// Vue3 示例 watch(route, (newRoute, oldRoute) => { console.log('参数变了', newRoute.params.id) // 这里做数据重新请求等操作 })
-
用组件内守卫
beforeRouteUpdate
(Vue2/Vue3都支持):beforeRouteUpdate(to, from, next) { console.log('路由更新,新参数是', to.params.id) next() // Vue2需要调用next,Vue3可省略或return }
嵌套路由怎么配置和使用?
嵌套路由用来实现「父组件里嵌套子组件」的场景(比如后台管理系统,左侧菜单栏是父组件,右侧内容区根据路由切换子组件)。
配置嵌套路由
在父路由的 children
数组里写子路由规则:
{ path: '/dashboard', // 父路由路径 component: Dashboard, // 父组件 children: [ { path: '', component: DashboardHome }, // 默认子路由,访问/dashboard时显示 { path: 'settings', component: DashboardSettings }, // 访问/dashboard/settings时显示 { path: 'profile', component: DashboardProfile } ] }
父组件里放 <router-view>
父组件(比如Dashboard.vue)的模板里,得有 <router-view>
来渲染子组件:
<template> <div class="dashboard"> <aside>左侧菜单</aside> <main> <router-view></router-view> <!-- 子组件渲染在这里 --> </main> </div> </template>
这样,访问 /dashboard/settings
时,Dashboard组件渲染,同时Settings子组件渲染到父组件的 <router-view>
位置。
路由守卫有哪些?分别在啥场景用?
路由守卫是「路由跳转前后的钩子函数」,用来做权限验证、数据加载、页面跳转拦截这些事,分三大类:
全局守卫(作用于所有路由)
-
router.beforeEach
:路由跳转前触发(全局前置守卫),常用作权限控制。
例子:判断用户是否登录,没登录跳登录页:router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !isLogin()) { next({ name: 'Login' }) // 跳登录页 } else { next() // 放行 } })
Vue3里可以不用
next
,直接return
目标路由或false
:router.beforeEach((to, from) => { if (to.meta.requiresAuth && !isLogin()) { return { name: 'Login' } } })
-
router.beforeResolve
:导航确认前触发(所有组件内守卫和路由独享守卫执行完后),少用,了解即可。 -
router.afterEach
:路由跳转完成后触发(全局后置守卫),常用作设置页面标题:router.afterEach((to) => { document.title = to.meta.title || '默认标题' })
路由独享守卫(作用于单个路由)
在路由规则里写 beforeEnter
,比如某个页面需要单独验证权限:
{ path: '/order', component: Order, beforeEnter: (to, from, next) => { if (hasOrderPermission()) { next() } else { next({ name: 'Forbidden' }) } } }
组件内守卫(作用于组件内)
-
beforeRouteEnter
:进入组件前触发(组件实例还没创建,所以拿不到this
),适合提前请求数据:beforeRouteEnter(to, from, next) { fetchData().then(data => { next(vm => { // vm是组件实例,进入后把数据给vm vm.data = data }) }) }
-
beforeRouteUpdate
:路由参数变化时触发(组件复用场景,比如/user/1
→/user/2
),前面讲动态路由时提过。 -
beforeRouteLeave
:离开组件前触发,常用作阻止误操作(比如表单没保存):beforeRouteLeave(to, from, next) { if (this.formDirty) { if (window.confirm('表单没保存,确定离开?')) { next() } else { next(false) // 取消离开 } } else { next() } }
路由懒加载怎么实现?有啥好处?
路由懒加载是「把组件打包成单独的JS文件,访问时再加载」,能减小首屏bundle体积,加快首屏加载速度。
实现方式
用 ES6 的 import()
函数代替直接 import
组件。
{ path: '/about', component: () => import('./views/About.vue') // 懒加载,打包时生成单独chunk }
对比「非懒加载」:
import About from './views/About.vue' // 会把About打包进主JS,首屏加载时一起加载 { path: '/about', component: About }
好处
- 首屏加载更快:只加载首页必要代码,其他页面按需加载;
- 代码分割更细:不同路由组件分开打包,避免单个JS文件过大;
- 缓存友好:用户访问过的页面,下次再访问会从缓存取。
路由元信息(meta)有啥用?怎么玩?
路由元信息是给路由规则加 meta
字段,存自定义数据(比如权限、页面标题、是否需要缓存组件)。
配置meta
在路由规则里加:
{ path: '/admin', component: Admin, meta: { requiresAuth: true, // 需要登录 '管理后台', // 页面标题 keepAlive: true // 是否缓存组件 } }
读取meta
- 全局守卫里读:
router.beforeEach
里判断to.meta.requiresAuth
(前面权限验证的例子); - 组件内读:用
$route.meta
(Vue2)或useRoute().meta
(Vue3); - 全局后置守卫改标题:
router.afterEach
里用to.meta.title
(前面改页面标题的例子)。
还能结合 <keep-alive>
实现组件缓存:根据 meta.keepAlive
决定是否缓存组件~
404页面咋配置?路由优先级要注意啥?
404页面用来处理「用户访问不存在的路径」的情况,配置时要注意路由匹配的优先级。
配置通配符路由
用 /:pathMatch(.*)*
匹配所有未定义的路径:
{ path: '/:pathMatch(.*)*', // 匹配所有路径 name: 'NotFound', component: () => import('./views/NotFound.vue') }
路由优先级
Vue-router 是「从上到下匹配路由规则,一旦匹配到就渲染」,所以404路由要放在routes数组的最后面,否则前面的路由还没匹配,就被404截胡了。
比如正确顺序:
const routes = [ { path: '/', component: Home }, { path: '/user/:id', component: User }, { path: '/:pathMatch(.*)*', component: NotFound } // 最后放404 ]
Vue2和Vue3的vue-router API有啥区别?
Vue2用 vue-router@3.x
,Vue3用 vue-router@4.x
,核心功能一样,但API和实现有不少变化:
创建路由的方式
- Vue2:
new VueRouter({ mode: 'history', routes })
; - Vue3:
createRouter({ history: createWebHistory(), routes })
(history模式),hash模式用createWebHashHistory
。
组合式API(Vue3新增)
Vue3里可以用 useRouter
、useRoute
钩子,代替Vue2里的 this.$router
、this.$route
:
// Vue3 setup 里 import { useRouter, useRoute } from 'vue-router' const router = useRouter() const route = useRoute()
响应式与守卫写法
Vue3中,route
是响应式对象,用 watch
监听更方便;路由守卫里的 next
可选,推荐用return
控制导航。
模式配置
Vue2的 mode: 'history'
对应Vue3的 createWebHistory()
,mode: 'hash'
对应 createWebHashHistory()
。
路由跳转时的query和params有啥不同?
传参时选query还是params,得看「参数是否要留在url里」「刷新后是否保留」这些需求~
query参数
- 特点:拼在url的查询字符串里(
/search?keyword=vue
); - 刷新后还在:因为参数在url里;
- 传参方式:
{ path: '/search', query: { keyword: 'vue' }}
或router.push({ path: '/search', query: { keyword: 'vue' }})
; - 取值:
$route.query.keyword
(Vue2)或useRoute().query.keyword
(Vue3)。
params参数
- 特点:有两种场景——
① 配合动态路由(/user/:id
),参数在url里(/user/123
),刷新后保留;
② 命名路由传参({ name: 'User', params: { id: 123 }}
),参数不在url里,刷新后丢失(除非配了动态路由); - 传参方式:必须用「命名路由」,不能直接传path(因为path里没动态段的话,params会被忽略);
- 取值:
$route.params.id
(Vue2)或useRoute().params.id
(Vue3)。
怎么选?
- 想让参数刷新后还在,且愿意暴露在url里→用query;
- 想让参数在url里(如用户ID)→配动态路由+params;
- 临时传参、刷新后不需要保留→用命名路由的params(但要注意刷新丢失问题)。
看完这些问题,你对vue-router API的核心用法应该清晰多了~ 实际项目里,把「路由配置+跳转+守卫+元信息」这些知识点结合起来,就能搞定权限控制、页面跳转、组件复用这些常见需求,要是还有细节没吃透,建议去官方文档里针对性查案例,多写几个小demo练手,用熟了自然就顺手啦~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。