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

八、结语

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

相关推荐
夏鹏今天学习了吗6 小时前
【性能优化】前端高性能优化策略
前端·性能优化
weixin_427771619 小时前
css font-size 的妙用
前端·css
凤凰战士芭比Q10 小时前
web中间件——Nginx
前端·nginx·中间件
一 乐10 小时前
点餐|智能点餐系统|基于java+ Springboot的动端的点餐系统小程序(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·小程序·论文
视图猿人11 小时前
RxJS基本使用及在next.js中使用的例子
开发语言·javascript
bitbitDown11 小时前
从零打造一个 Vite 脚手架工具:比你想象的简单多了
前端·javascript·面试
liangshanbo121512 小时前
CSS 数学函数完全指南:从基础计算到高级动画
前端·css
码上成长13 小时前
GraphQL:让前端自己决定要什么数据
前端·后端·graphql
冴羽13 小时前
为什么在 JavaScript 中 NaN !== NaN?背后藏着 40 年的技术故事
前端·javascript·node.js