Vue编程式路由导航

一、前言

在 Vue 开发中,页面跳转通常使用 <router-link> 标签实现声明式导航:

html 复制代码
<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?)

用途:向浏览器历史栈添加一条新记录,点击"后退"可以返回。

适用场景:普通页面跳转,如"提交 → 成功页"。

✅ 基本用法
javascript 复制代码
// 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,否则参数会丢失!

✅ 完整对象格式
javascript 复制代码
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 页面、表单防重复提交。

✅ 基本用法
javascript 复制代码
// 替换当前页面
this.$router.replace('/login')

// 对象形式
this.$router.replace({
  path: '/404',
  query: { msg: '页面不存在' }
})

💡 效果相当于:

javascript 复制代码
this.$router.push({ path: '/login', replace: true })

3. router.go(n)

用途:在浏览器历史记录中前进或后退 n 步。

适用场景:自定义"返回上一页"按钮、多步表单导航。

✅ 基本用法
javascript 复制代码
// 后退一步
this.$router.go(-1)
this.$router.back() // 等价写法

// 前进一步
this.$router.go(1)
this.$router.forward() // 等价写法

// 后退两步
this.$router.go(-2)

// 如果历史记录不足,会静默失败(不报错)
this.$router.go(-100) // 无效果

四、实战场景示例

场景1:表单提交后跳转

html 复制代码
<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:登录成功后跳转

javascript 复制代码
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:权限校验拦截

javascript 复制代码
// 全局守卫中使用
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLogin()) {
    // 未登录,跳转登录页,并记录来源
    next({
      path: '/login',
      query: { redirect: to.fullPath }
    })
  } else {
    next()
  }
})
html 复制代码
<!-- Login.vue -->
<script>
export default {
  mounted() {
    // 登录成功后跳回原页面
    const redirect = this.$route.query.redirect || '/home'
    this.$router.replace(redirect)
  }
}
</script>

场景4:自定义返回按钮

html 复制代码
<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,可以捕获错误:

javascript 复制代码
this.$router.push('/home').catch(err => {
  // 避免 "NavigationDuplicated" 错误(重复跳转同一页面)
  if (err.name !== 'NavigationDuplicated') {
    console.error(err)
  }
})

💡 常见错误:NavigationDuplicated,表示重复跳转到同一路由。

2. 防止重复跳转

javascript 复制代码
// 封装安全跳转方法
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 获取:

javascript 复制代码
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() 前进一步 - 前进一页

最佳实践

  1. 优先使用 name + params 跳转,更稳定
  2. 复杂跳转使用对象形式
  3. 捕获跳转错误,避免白屏
  4. 在 Composition API 中使用 useRouter

八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
崔庆才丨静觅18 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606119 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了19 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅19 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅19 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅20 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment20 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅20 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊20 小时前
jwt介绍
前端
爱敲代码的小鱼20 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax