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前端网发表,如需转载,请注明页面地址。
code前端网




发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。