Vue编程式路由导航
一、前言
在 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) {// 保存 tokenlocalStorage.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') returnthrow 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
八、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!
