一、Vue Router Object 是个啥?
p>做Vue项目开发时,路由功能几乎是刚需,但很多同学刚接触Vue Router,对「Vue Router Object」总是一知半解:它到底是什么?怎么在组件里调用?动态路由、权限控制这些场景怎么靠它实现?今天咱们就把这个Vue路由的核心对象拆开讲,从基础概念到实战避坑,一次性搞懂!
你可以把它理解成整个Vue项目的“路由大管家”——所有路由规则、页面跳转逻辑、当前路由状态,都由这个对象统一管理。
先看创建它的代码:
// router.js 文件
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: () => import('./views/About.vue') }
]
// 这里创建的 router Vue Router Object!
const router = createRouter({
history: createWebHistory(), // 路由模式(history/hash)
routes // 路由规则数组
})
export default router
这个router对象一旦创建,就会成为单例(整个项目就这一个),负责:
- 存储所有路由规则(比如对应Home组件,
/about对应About组件); - 提供「跳转页面」「前进后退」这些方法(像
router.push、router.go); - 记录当前路由状态(比如现在在哪个页面、URL里的参数是啥,对应
router.currentRoute); - 处理导航守卫(比如页面跳转前判断用户是否登录,对应
router.beforeEach)。
简单说:它是Vue Router的“心脏”,路由功能的方方面面都得靠它运转。
Vue Router Object 有哪些核心“技能”?
要用好这个大管家,得先摸清它的核心属性和方法,可以分成“状态属性”和“操作方法”两类。
核心属性:看状态
-
router.currentRoute:当前路由的详细信息(响应式的!),比如你在/user/123?tab=info页面,它会包含:{ path: '/user/123', params: { id: '123' }, query: { tab: 'info' }, name: 'user', // 路由命名的话才有 meta: { ... } // 路由元信息 }在组件里,用
useRoute()(组合式API)或this.$route(选项式API)能拿到这个对象,而且它会自动响应式更新(参数变了、路径变了,它也会变)。 -
router.options:创建路由时的“原始配置”,比如你初始化时传的routes数组、history模式,都存在这里,一般调试或动态路由时会用到。
核心方法:做操作
路由跳转、动态加路由、前进后退…全靠这些方法:
-
router.push():最常用的“跳转到新页面”,它会往浏览器历史栈里新增一条记录(点返回能回到上一页),用法灵活:// 方式1:直接写路径字符串 router.push('/user/123') // 方式2:命名路由 + 动态参数(推荐!解耦路径和参数) router.push({ name: 'user', params: { id: 123 } }) // 方式3:带查询参数(?后面的部分) router.push({ path: '/user', query: { tab: 'profile' } }) -
router.replace():和push类似,但它会替换当前历史记录(点返回不会回到当前页,而是更前一页),比如支付成功后跳结果页,用replace避免用户回退又到支付页。 -
router.go(n):控制历史记录的前进后退,n是数字,比如router.go(1)前进一页,router.go(-1)后退一页,和浏览器的「前进/后退」按钮逻辑一样。 -
router.back()/router.forward():go(-1)和go(1)的快捷写法,更语义化。 -
router.addRoute()/router.removeRoute():动态添加/删除路由规则。权限管理、异步路由的核心!比如后台系统,管理员登录后才加载/admin路由:// 登录后,给管理员加专属路由 if (user.role === 'admin') { router.addRoute({ path: '/admin', component: () => import('./views/Admin.vue') }) }
组件里怎么“喊”这个大管家?
路由对象是单例,但在不同场景(组件内、组件外)访问方式不一样。
组件内部:用钩子函数
Vue 3的组合式API里,用useRouter()和useRoute():
<template>
<button @click="goToAbout">去关于页</button>
</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter() // 拿到路由对象
function goToAbout() {
router.push('/about') // 跳转
}
</script>
Vue 2的选项式API,或者Vue 3里用选项式写法,用this.$router和this.$route(前提是Vue实例里注入了路由):
export default {
methods: {
goToAbout() {
this.$router.push('/about')
}
}
}
注意:想拿“当前路由信息”(比如参数、查询参数),用useRoute()或this.$route;想“操作路由”(跳转、加路由),用useRouter()或this.$router。
组件外部:直接导入实例
如果在Vuex仓库、工具函数、JS文件里操作路由,直接导入创建好的router实例就行:
// router.js(创建路由的文件)
export const router = createRouter({ ... }) // 注意要导出
// utils/auth.js(工具文件)
import { router } from '../router.js'
// 登录成功后跳转
function loginSuccess() {
router.push('/dashboard')
}
实战:用Vue Router Object 搞动态路由、权限控制
很多复杂场景(比如权限路由、多租户系统),核心就是动态增删路由 + 导航守卫。
场景1:根据用户权限加载路由(动态路由)
后台系统里,普通用户看不到/admin页面,管理员登录后才加载这个路由,步骤:
- 先在路由规则里写个“占位符”(可选,也可以完全动态加);
- 登录成功后,用
router.addRoute()加管理员路由; - 用导航守卫(
router.beforeEach)拦截未授权访问。
代码示例:
// router.js 初始化时,先不加/admin路由
const routes = [
{ path: '/login', component: Login },
{ path: '/', component: Home, meta: { requiresAuth: true } }
]
const router = createRouter({ ... })
// 全局前置守卫:跳转前检查权限
router.beforeEach((to, from, next) => {
// 如果目标页面需要登录,且用户没登录,跳登录页
if (to.meta.requiresAuth && !isLoggedIn()) {
next({ name: 'login' })
} else {
next() // 放行
}
})
// 登录逻辑(比如在Login组件里)
function handleLogin() {
// 假设登录后拿到用户角色
const user = loginApi()
if (user.role === 'admin') {
// 动态添加管理员路由
router.addRoute({
path: '/admin',
component: () => import('./views/Admin.vue'),
meta: { requiresAuth: true }
})
}
// 跳转到首页
router.push('/')
}
场景2:路由元信息(meta)控制页面行为
路由元信息是给路由“贴标签”的,比如标记“是否需要登录”“页面标题”“过渡动画”。
配置路由时加meta:
{
path: '/profile',
component: Profile,
meta: {
requiresAuth: true, '个人中心',
transition: 'fade' // 过渡动画名称
}
}
然后在导航守卫里用to.meta做逻辑:
router.beforeEach((to, from, next) => {
// 设置页面标题
document.title = to.meta.title || '默认标题'
next()
})
或者在组件里根据meta做过渡动画:
<router-view v-slot="{ Component, route }">
<Transition :name="route.meta.transition || 'slide'">
<component :is="Component" />
</Transition>
</router-view>
避坑指南:这些问题90%的人都踩过
路由开发时,有些“玄学”问题其实是对路由对象理解不到位导致的,这里列几个高频坑:
坑1:路由跳转后,组件没更新
比如从/user/1跳到/user/2,URL变了但页面数据没刷新。原因是Vue复用了相同组件(路径结构一样,只是参数变了),组件的生命周期没触发。
解决方法:
- 监听路由变化:在组件里用
watch监听$route(或useRoute())的变化,参数变了就重新请求数据。// 组合式API import { useRoute, watch } from 'vue-router' const route = useRoute() watch(route, (newRoute) => { // newRoute.params.id 变化了,重新请求数据 fetchUser(newRoute.params.id) }) - 给组件加key:让Vue认为是不同组件,强制销毁重建。
<template> <UserComponent :key="$route.params.id" /> </template>
坑2:动态加路由重复了
多次调用router.addRoute()会导致同一路由被重复添加,页面可能出问题。解决方法是先检查是否已存在:
if (!router.hasRoute('admin')) { // hasRoute 检查路由是否存在(按name判断)
router.addRoute({ name: 'admin', path: '/admin', component: Admin })
}
坑3:history模式下刷新页面404
用createWebHistory()(history模式)时,直接刷新页面,后端如果没配置,会返回404。原因是前端路由走的是HTML5 History API,后端不认识前端的路由路径。
解决:让后端把所有前端路由的请求,都转发到index.html,比如Nginx配置:
location / {
try_files $uri $uri/ /index.html;
}
坑4:导航守卫里next()用错了
导航守卫(比如beforeEach)里的next()是控制导航是否继续的函数,必须确保只调用一次!比如异步逻辑里没处理好,就会报错。
错误示例(多次调用next):
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
next({ name: 'login' }) // 这里调了next
}
next() // 又调了next,重复调用会报错!
})
正确写法(确保只调一次):
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isLoggedIn()) {
next({ name: 'login' })
} else {
next() // 只在else里调
}
})
进阶:路由对象还能玩出啥花样?
除了基础功能,结合Vue生态,路由对象能搞很多高阶玩法:
路由过渡动画的精细化控制
不同页面用不同过渡效果,靠route.meta.transition动态切换:
<router-view v-slot="{ Component, route }">
<Transition :name="route.meta.transition">
<component :is="Component" />
</Transition>
</router-view>
然后在路由配置里指定:
{
path: '/home',
component: Home,
meta: { transition: 'slide-left' }
},
{
path: '/about',
component: About,
meta: { transition: 'slide-right' }
}
路由懒加载 + 进度条
结合import()懒加载和NProgress进度条,路由跳转时显示加载状态:
// 全局路由守卫里加进度条逻辑
import NProgress from 'nprogress'
router.beforeEach((to, from, next) => {
NProgress.start() // 开始加载
next()
})
router.afterEach(() => {
NProgress.done() // 加载完成
})
// 路由规则里用懒加载
{
path: '/about',
component: () => {
NProgress.set(0.5) // 加载到一半时设进度
return import('./views/About.vue')
}
}
多标签页(类似浏览器标签)
模拟多标签页功能,用router.push配合keep-alive和标签数组,记录用户打开的页面:
// 存储打开的标签页
const visitedTabs = ref([])
function openTab(path) {
if (!visitedTabs.value.includes(path)) {
visitedTabs.value.push(path)
}
router.push(path)
}
// 模板里循环渲染标签
<template>
<div v-for="path in visitedTabs" :key="path">
<button @click="router.push(path)">{{ path }}</button>
</div>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>
掌握Vue Router Object 等于掌控路由命脉
从基础的“是什么”,到核心的“怎么用”,再到实战的“怎么玩出花”,Vue Router Object 贯穿了路由开发的全流程,理解它的属性、方法,结合导航守卫、动态路由、元信息这些工具,不管是简单的页面跳转,还是复杂的权限管理、多端适配,都能游刃有余。
最后再强调个心法:路由对象是“管理者”,它的一切设计都是为了让路由逻辑更集中、更可控,遇到路由问题时,先想“路由对象能提供什么方法/属性”,很多问题自然就有了方向~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网


