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) {
    // 保存 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()前进一步-前进一页

最佳实践

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

八、结语

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值