一、前言
在 Vue 开发中,页面跳转通常使用 <router-link> 标签实现声明式导航:
<router-link to="/home">首页</router-link>
但很多时候,我们需要在 JavaScript 代码中控制跳转,比如:
- 表单提交成功后跳转到列表页
- 登录成功后自动跳转到首页
- 权限校验失败时返回登录页
- 点击按钮、监听事件、异步操作后跳转
这些场景就需要使用 编程式导航(Programmatic Navigation)。
本文将带你: ✅ 全面掌握 router.push()、replace()、go() 等核心 API
✅ 理解命名路由、参数传递、跳转选项
✅ 避开常见坑点,写出健壮的跳转逻辑
✅ 提供完整代码示例,拿来即用
二、什么是编程式导航?
| 类型 | 说明 | 示例 |
|---|---|---|
| 声明式导航 | 通过模板标签跳转 | <router-link to="/home"> |
| 编程式导航 | 通过 JavaScript 控制跳转 | this.$router.push('/home') |
✅ 编程式导航 = 在 JS 中调用
router实例的方法来跳转
三、核心 API 详解
1. router.push(location, onComplete?, onAbort?)
用途:向浏览器历史栈添加一条新记录,点击“后退”可以返回。
适用场景:普通页面跳转,如“提交 → 成功页”。
✅ 基本用法
// 1. 字符串路径
this.$router.push('/home')
// 2. 带参数的对象
this.$router.push({
path: '/user',
query: { id: 123 } // ?id=123
})
// 3. 使用命名路由(推荐)
this.$router.push({
name: 'UserProfile',
params: { id: 456 } // /user/456
})
⚠️ 注意:使用
params时,必须使用name,不能用path,否则参数会丢失!
✅ 完整对象格式
this.$router.push({
name: 'Detail',
params: { id: 1 },
query: { from: 'list' },
hash: '#section2',
// 跳转完成后的回调(可选)
onComplete: (to) => {
console.log('跳转成功', to)
},
// 跳转被中断的回调(可选)
onAbort: (from) => {
console.log('跳转中断', from)
}
})
2. router.replace(location, onComplete?, onAbort?)
用途:替换当前历史记录,不会新增记录,点击“后退”不会回到原页面。
适用场景:登录页、404 页面、表单防重复提交。
✅ 基本用法
// 替换当前页面
this.$router.replace('/login')
// 对象形式
this.$router.replace({
path: '/404',
query: { msg: '页面不存在' }
})
💡 效果相当于:
this.$router.push({ path: '/login', replace: true })
3. router.go(n)
用途:在浏览器历史记录中前进或后退 n 步。
适用场景:自定义“返回上一页”按钮、多步表单导航。
✅ 基本用法
// 后退一步
this.$router.go(-1)
this.$router.back() // 等价写法
// 前进一步
this.$router.go(1)
this.$router.forward() // 等价写法
// 后退两步
this.$router.go(-2)
// 如果历史记录不足,会静默失败(不报错)
this.$router.go(-100) // 无效果
四、实战场景示例
场景1:表单提交后跳转
<template>
<form @submit="handleSubmit">
<input v-model="username" placeholder="用户名" />
<button type="submit">提交</button>
</form>
</template>
<script>
export default {
data() {
return {
username: ''
}
},
methods: {
async handleSubmit(e) {
e.preventDefault()
try {
await submitForm(this.username) // 模拟提交
// 跳转到成功页
this.$router.push({
path: '/success',
query: { user: this.username }
})
} catch (err) {
alert('提交失败')
}
}
}
}
</script>
场景2:登录成功后跳转
async login() {
const { data } = await api.login(this.form)
if (data.success) {
// 保存 token
localStorage.setItem('token', data.token)
// 跳转到首页
this.$router.push('/dashboard')
// 或跳转到来源页
const from = this.$route.query.redirect || '/dashboard'
this.$router.push(from)
}
}
场景3:权限校验拦截
// 全局守卫中使用
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isLogin()) {
// 未登录,跳转登录页,并记录来源
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
})
<!-- Login.vue -->
<script>
export default {
mounted() {
// 登录成功后跳回原页面
const redirect = this.$route.query.redirect || '/home'
this.$router.replace(redirect)
}
}
</script>
场景4:自定义返回按钮
<template>
<div>
<button @click="goBack">返回上一页</button>
</div>
</template>
<script>
export default {
methods: {
goBack() {
// 方式1:直接后退
this.$router.back()
// 方式2:带判断的后退
if (window.history.length > 1) {
this.$router.go(-1)
} else {
// 如果没有上一页,跳转到首页
this.$router.push('/')
}
}
}
}
</script>
五、高级技巧与注意事项
1. 跳转失败的处理
router.push() 返回一个 Promise,可以捕获错误:
this.$router.push('/home').catch(err => {
// 避免 "NavigationDuplicated" 错误(重复跳转同一页面)
if (err.name !== 'NavigationDuplicated') {
console.error(err)
}
})
💡 常见错误:
NavigationDuplicated,表示重复跳转到同一路由。
2. 防止重复跳转
// 封装安全跳转方法
function safePush(router, location) {
return router.push(location).catch(err => {
if (err.name === 'NavigationDuplicated') return
throw err
})
}
// 使用
safePush(this.$router, '/home')
3. 在 Composition API 中使用
Vue 3 的 setup 中无法使用 this,需通过 useRouter 获取:
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
const goToHome = () => {
router.push('/home')
}
return { goToHome }
}
}
六、push vs replace 对比
| 方法 | 是否新增历史记录 | 后退能否返回 | 适用场景 |
|---|---|---|---|
push() | ✅ 是 | ✅ 可以 | 普通跳转 |
replace() | ❌ 否 | ❌ 不行 | 登录、404、防重复 |
📌 口诀:
- 想让用户能“返回” → 用
push- 不想让用户“返回” → 用
replace
七、总结
| API | 作用 | 是否新增记录 | 典型场景 |
|---|---|---|---|
router.push() | 跳转到新页面 | ✅ 是 | 表单提交、页面导航 |
router.replace() | 替换当前页面 | ❌ 否 | 登录、404、重定向 |
router.go(n) | 前进/后退 n 步 | - | 自定义返回按钮 |
router.back() | 后退一页 | - | 返回上一页 |
router.forward() | 前进一步 | - | 前进一页 |
✅ 最佳实践:
- 优先使用
name+params跳转,更稳定- 复杂跳转使用对象形式
- 捕获跳转错误,避免白屏
- 在 Composition API 中使用
useRouter
八、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!
2446

被折叠的 条评论
为什么被折叠?



