router.push
基本用法
router.push() 会向 history 栈添加新记录,点击后退按钮可以返回之前的 URL。
javascript
// 字符串路径
router.push('/home')
// 对象路径
router.push({ path: '/home' })
// 命名路由
router.push({ name: 'Home' })
// 带查询参数
router.push({ path: '/user', query: { id: '123' } })参数类型
javascript
// 1. 字符串
router.push('/user/123')
// 2. 对象
router.push({ path: '/user/123' })
// 3. 命名路由
router.push({ name: 'User', params: { id: '123' } })
// 4. 带查询参数
router.push({ path: '/user', query: { id: '123' } })
// URL: /user?id=123
// 5. 带 hash
router.push({ path: '/user', hash: '#section' })
// URL: /user#section完整签名
javascript
router.push(location, onComplete?, onAbort?)参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
location | string | object | 路由位置信息 |
onComplete | Function | 导航成功完成的回调 |
onAbort | Function | 导航中止的回调 |
使用示例
在组件内
javascript
export default {
methods: {
goToHome() {
this.$router.push('/home')
},
goToUser() {
this.$router.push({
name: 'User',
params: { id: 123 }
})
},
goToSearch() {
this.$router.push({
path: '/search',
query: {
q: 'vue router',
page: 1
}
})
}
}
}带回调
javascript
this.$router.push(
'/home',
() => {
console.log('导航成功')
},
() => {
console.log('导航中止')
}
)Promise 用法
Vue Router 3.1+ 支持 Promise:
javascript
// 返回 Promise
this.$router.push('/home')
.then(() => {
console.log('导航成功')
})
.catch(err => {
console.log('导航失败:', err)
})
// 使用 async/await
async function navigate() {
try {
await this.$router.push('/home')
console.log('导航成功')
} catch (err) {
console.log('导航失败:', err)
}
}params 与 query 的区别
javascript
// params - 作为 URL 的一部分
router.push({ name: 'User', params: { id: '123' } })
// URL: /user/123 (需要在路由中定义 /user/:id)
// query - 作为查询参数
router.push({ path: '/user', query: { id: '123' } })
// URL: /user?id=123注意
如果提供了 path,params 会被忽略:
javascript
// ❌ params 会被忽略
router.push({ path: '/user', params: { id: '123' } })
// URL: /user
// ✅ 使用 query 或命名路由
router.push({ path: '/user', query: { id: '123' } })
router.push({ name: 'User', params: { id: '123' } })router.replace
基本用法
router.replace() 与 router.push() 类似,但不会向 history 栈添加新记录,而是替换当前记录。
javascript
// 字符串
router.replace('/home')
// 对象
router.replace({ path: '/home' })
// 命名路由
router.replace({ name: 'Home' })与 push 的区别
javascript
// 使用 push - 可以后退
router.push('/page1')
router.push('/page2')
// 历史记录: [page1, page2]
// 后退按钮可以回到 page1
// 使用 replace - 不能后退
router.push('/page1')
router.replace('/page2')
// 历史记录: [page2]
// 后退按钮不能回到 page1应用场景
- 登录后跳转(不保留登录页)
- 表单提交成功后(不保留表单页)
- 重置密码后(不保留重置页)
javascript
// 登录成功
async login() {
const success = await this.$api.login(this.form)
if (success) {
// 替换当前记录,后退时不会回到登录页
this.$router.replace('/dashboard')
}
}
// 表单提交
async submitForm() {
await this.$api.submitForm(this.form)
// 替换当前记录,防止重复提交
this.$router.replace('/success')
}声明式写法
Vue SFC
<router-link to="/home" replace>首页</router-link>router.go
基本用法
router.go(n) 在 history 记录中前进或后退 n 步。
javascript
// 前进 1 步(等同于 router.forward())
router.go(1)
// 后退 1 步(等同于 router.back())
router.go(-1)
// 前进 3 步
router.go(3)
// 后退 2 步
router.go(-2)超出范围
如果 history 记录不够,router.go() 会静默失败:
javascript
// 假设 history 只有 2 条记录
router.go(-100) // 静默失败,什么都不会发生
router.go(100) // 静默失败,什么都不会发生简化方法
javascript
// 后退
router.back()
// 等同于
router.go(-1)
// 前进
router.forward()
// 等同于
router.go(1)应用示例
Vue SFC
<template>
<div>
<button @click="goBack">返回</button>
<button @click="goForward">前进</button>
<button @click="goHome">返回首页</button>
</div>
</template>
<script>
export default {
methods: {
goBack() {
this.$router.back()
},
goForward() {
this.$router.forward()
},
goHome() {
this.$router.push('/')
}
}
}
</script>导航位置对象
location 参数可以是字符串或对象,对象形式提供更多选项。
完整属性
javascript
{
path: '/user', // 路径
name: 'User', // 命名路由
params: { id: '123' }, // 路由参数
query: { page: 1 }, // 查询参数
hash: '#section', // hash 值
// 完整 URL 示例: /user?page=1#section
}属性说明
| 属性 | 类型 | 说明 |
|---|---|---|
path | string | 路由路径 |
name | string | 路由名称 |
params | object | 路由参数(需配合命名路由或动态路由) |
query | object | URL 查询参数 |
hash | string | URL hash 值 |
组合示例
javascript
// 命名路由 + params
router.push({
name: 'UserDetail',
params: { id: '123' }
})
// URL: /user/123
// path + query
router.push({
path: '/search',
query: { q: 'vue', page: 1 }
})
// URL: /search?q=vue&page=1
// name + params + query
router.push({
name: 'Product',
params: { category: 'phone' },
query: { sort: 'price' }
})
// URL: /product/phone?sort=price
// path + hash
router.push({
path: '/article',
hash: '#comments'
})
// URL: /article#comments导航控制
导航确认
使用 onComplete 和 onAbort 回调:
javascript
this.$router.push(
'/user/123',
() => {
// 导航成功完成
console.log('导航成功')
},
() => {
// 导航中止(被导航守卫阻止或跳转到其他路由)
console.log('导航中止')
}
)Promise 模式
javascript
// Vue Router 3.1+
try {
await this.$router.push('/user/123')
console.log('导航成功')
} catch (error) {
if (error.name === 'NavigationDuplicated') {
console.log('重复导航')
} else {
console.log('导航中止:', error)
}
}处理导航重复
Vue Router 3.1+ 会抛出 NavigationDuplicated 错误:
javascript
// 全局处理
import VueRouter from 'vue-router'
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => {
if (err.name !== 'NavigationDuplicated') {
return Promise.reject(err)
}
})
}
// 或者在调用时捕获
this.$router.push('/home').catch(err => {})实战示例
登录后跳转
Vue SFC
<template>
<form @submit.prevent="handleLogin">
<input v-model="form.username" placeholder="用户名" />
<input v-model="form.password" type="password" placeholder="密码" />
<button type="submit">登录</button>
</form>
</template>
<script>
export default {
data() {
return {
form: {
username: '',
password: ''
}
}
},
methods: {
async handleLogin() {
try {
await this.$store.dispatch('user/login', this.form)
// 登录成功,跳转到之前要访问的页面或首页
const redirect = this.$route.query.redirect || '/'
this.$router.replace(redirect)
this.$message.success('登录成功')
} catch (error) {
this.$message.error('登录失败:' + error.message)
}
}
}
}
</script>表单提交后跳转
javascript
export default {
methods: {
async submitForm() {
try {
const id = await this.$api.createArticle(this.form)
// 跳转到详情页
this.$router.push({
name: 'ArticleDetail',
params: { id }
})
this.$message.success('创建成功')
} catch (error) {
this.$message.error('创建失败')
}
}
}
}带确认的导航
javascript
export default {
methods: {
leavePage() {
if (this.hasUnsavedChanges) {
this.$confirm('有未保存的更改,确定要离开吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$router.push('/home')
}).catch(() => {
// 取消导航
})
} else {
this.$router.push('/home')
}
}
}
}条件导航
javascript
export default {
methods: {
handleNavigate(role) {
// 根据用户角色跳转到不同页面
const routes = {
admin: '/admin/dashboard',
user: '/user/home',
guest: '/login'
}
this.$router.push(routes[role] || '/')
}
}
}定时跳转
Vue SFC
<template>
<div class="countdown">
<p>{{ countdown }} 秒后跳转到首页</p>
<router-link to="/">立即跳转</router-link>
</div>
</template>
<script>
export default {
data() {
return {
countdown: 5,
timer: null
}
},
mounted() {
this.timer = setInterval(() => {
this.countdown--
if (this.countdown <= 0) {
clearInterval(this.timer)
this.$router.replace('/')
}
}, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}
}
</script>完整示例:导航工具函数
javascript
// utils/navigation.js
/**
* 导航到指定路由
*/
export function navigateTo(router, location, replace = false) {
const method = replace ? 'replace' : 'push'
return router[method](location).catch(err => {
if (err.name !== 'NavigationDuplicated') {
throw err
}
})
}
/**
* 返回上一页或指定页面
*/
export function goBack(router, fallback = '/') {
if (window.history.length > 1) {
router.back()
} else {
router.replace(fallback)
}
}
/**
* 刷新当前页面
*/
export function refreshPage(router) {
const { path, query, params } = router.currentRoute
router.replace({ path, query, params })
}
/**
* 打开新标签页
*/
export function openInNewTab(router, location) {
const route = router.resolve(location)
window.open(route.href, '_blank')
}使用示例:
javascript
import { navigateTo, goBack, refreshPage, openInNewTab } from '@/utils/navigation'
// 导航
await navigateTo(this.$router, '/user/123')
// 返回
goBack(this.$router, '/home')
// 刷新
refreshPage(this.$router)
// 新标签页打开
openInNewTab(this.$router, '/user/123')最佳实践
1. 优先使用命名路由
javascript
// ✅ 推荐:使用命名路由
router.push({ name: 'UserDetail', params: { id: '123' } })
// ❌ 不推荐:硬编码路径
router.push('/user/123')2. 登录后使用 replace
javascript
// ✅ 推荐
this.$router.replace('/dashboard')
// ❌ 不推荐
this.$router.push('/dashboard') // 后退会回到登录页3. 捕获导航错误
javascript
// Vue Router 3.1+
this.$router.push('/home').catch(err => {
if (err.name !== 'NavigationDuplicated') {
console.error('导航错误:', err)
}
})4. 使用查询参数传递复杂数据
javascript
// 传递对象
router.push({
path: '/search',
query: {
filters: JSON.stringify({ category: 'phone', price: [100, 500] })
}
})
// 在目标组件解析
const filters = JSON.parse(this.$route.query.filters || '{}')5. 避免在导航守卫中使用 push
javascript
// ❌ 不推荐:可能导致无限循环
router.beforeEach((to, from, next) => {
if (!isAuthenticated()) {
router.push('/login') // 可能导致循环
return
}
next()
})
// ✅ 推荐:使用 next
router.beforeEach((to, from, next) => {
if (!isAuthenticated()) {
next('/login')
return
}
next()
})常见问题
1. params 丢失?
确保使用命名路由或动态路由:
javascript
// ❌ params 会被忽略
router.push({ path: '/user', params: { id: '123' } })
// ✅ 使用命名路由
router.push({ name: 'User', params: { id: '123' } })
// ✅ 使用动态路由
// 路由配置: { path: '/user/:id', name: 'User', ... }
router.push({ name: 'User', params: { id: '123' } })2. 如何传递大量数据?
使用 Vuex 或状态管理,而不是通过 URL:
javascript
// 存储数据
this.$store.commit('setTempData', largeData)
// 导航
this.$router.push('/preview')
// 在目标组件读取
const data = this.$store.state.tempData3. 如何在新窗口打开?
javascript
const route = this.$router.resolve('/user/123')
window.open(route.href, '_blank')4. 如何获取跳转前的路由?
javascript
// 在路由守卫中
router.afterEach((to, from) => {
console.log('从', from.path, '跳转到', to.path)
})
// 在组件中
this.$router.beforeEach((to, from, next) => {
console.log('来源路由:', from)
next()
})