Vue3学习历程杂记(2)
Vue Router 核心用法与常见问题详解
Vue Router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。本文将详细介绍 Vue Router 的核心概念、使用技巧以及常见问题的解决方案。
1. params 路由传参
params:路径隐式参数(动态路由参数),参数不拼接在 URL 地址栏,靠路由规则占位接收。
1.1 备注 1:to 对象写法传 params,只能用 name,不能写 path
正确写法(name + params,依靠路由命名匹配路由)
// ✅ 用 name 匹配路由规则,params 正常传递
router.push({
name: 'Detail', // 路由配置里的 name 字段
params: { id: 100 }
})
错误写法(path + params,params 失效、收不到参数)
// ❌ path 搭配 params,参数丢了,目标页面拿不到 params
router.push({
path: '/detail',
params: { id: 100 }
})
原理:path 是硬编码地址,无法绑定 params 参数;name 会去路由表里匹配规则,自动匹配动态占位符来装载 params。
1.2 备注 2:params 必须提前在路由规则 path 里占位
路由配置(必须提前用 :变量名 占位)
const routes = [
{
name: 'Detail', // 和 push 里 name 对应
path: '/detail/:id', // :id 就是 params 的占位符
component: Detail
}
]
:id:动态占位,将来params:{id:100}会填充这里,最终浏览器地址变成/detail/100
目标页面接收参数
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // 100
</script>
1.3 补充:params vs query 关键区分

2. replace 无历史记录
浏览器自带历史记录栈,前进后退按钮依赖这个栈,push/replace 就是修改栈的两种方式。
2.1 router.push()【默认跳转,追加历史】
新页面地址追加进历史栈,保留上一页记录,可以点返回按钮回到上一页。
历史栈变化示例:
[首页] → push 跳转详情 → [首页,详情]
2.2 router.replace()【替换当前历史,无返回】
新地址直接覆盖替换栈顶当前页面,不会新增历史记录,不能返回上一页。
历史栈变化示例:
[首页] → replace 跳转详情 → [详情]
在详情页点浏览器 ←,无法回到首页,直接跳出当前项目页面。
适用场景:登录页、支付页、404 页,不允许用户返回上一页重复操作。
示例:
前置:路由配置不变 router/index.js
const routes = [
{ path: '/', name: 'Home', component: () => import('@/views/Home.vue') },
{ path: '/detail/:id', name: 'Detail', component: () => import('@/views/Detail.vue') }
]
Home.vue(首页,跳转入口页面)
<template>
<div>
<h3>首页页面</h3>
<!-- 1. 默认 push:追加历史记录 -->
<router-link :to="{ name: 'Detail', params: { id: 101 } }">
【push 跳转详情】
</router-link>
<br/><br/>
<!-- 2. 加 replace 属性:替换当前历史 -->
<router-link replace :to="{ name: 'Detail', params: { id: 102 } }">
【replace 跳转详情】
</router-link>
</div>
</template>
3. $route 和 $router 核心区别

3.1 $route(拿参数、读地址)
只用来获取当前页面的URL、参数,不能跳转页面。
选项式 API 写法:
<!-- template里直接用 -->
<div>
<!-- 获取params参数 -->
{{ $route.params.id }}
<!-- 获取query参数 -->
{{ $route.query.name }}
<!-- 获取当前路径 -->
{{ $route.path }}
</div>
组合式 API 写法:
import { useRoute } from 'vue-router'
const route = useRoute()
// 获取参数
console.log(route.params.id) // params参数
console.log(route.query.name) // query参数
console.log(route.path) // 当前路径
3.2 $router(控制页面跳转)
全局路由实例,用来编程跳转、前进后退。
选项式 API 写法:
<template>
<button @click="goDetail">跳转</button>
</template>
<script>
export default {
methods: {
goDetail() {
// push追加历史跳转
this.$router.push({ name: 'Detail', params: { id: 10 } })
// replace替换跳转
// this.$router.replace('/home')
// 返回上一页
// this.$router.go(-1)
}
}
}
</script>
组合式 API 写法:
import { useRouter } from 'vue-router'
const router = useRouter()
// 跳转页面
router.push({ name: 'Detail', params: { id: 10 } })
router.replace('/home')
router.go(-1) // 返回上一页
3.3 一句话总结
- $route:查信息(取值) - 获取当前路由信息
- $router:改地址(跳转) - 控制路由跳转
3.4 配套对应(组合式 ↔ 选项式)
useRoute() ↔ this.$route
useRouter() ↔ this.$router
4. 编程式路由 router.push() 详解
<router-link to="xxx"> 标签 to 能写的格式,router.push(xxx) JS 里全能照搬,写法完全互通。
4.1 写法 1:纯字符串路径(搭配 query 传参,? 拼接参数)
// 等价 <router-link to="/detail?id=10">
router.push('/detail?id=10')
// 带多级路径
router.push('/home/detail')
参数在 URL:/detail?id=10,目标页面用 $route.query.id 取值。
4.2 写法 2:对象 path+query(query 用,不能配 params)
// 等价 <router-link :to="{path:'/detail',query:{id:20}}">
router.push({
path: '/detail',
query: { id: 20, name: 'IBM' }
})
// 地址:/detail?id=20&name=IBM
注意:path + params 会失效!params 必须用 name。
原理:path 是写死的完整路径字符串(/detail),VueRouter 拿到固定路径后,不会去路由配置表里匹配规则里的 :id 占位符,params 参数找不到可以填充的位置,直接被丢弃。
4.3 写法 3:对象 name+params
// 等价 <router-link :to="{name:'Detail',params:{id:30}}">
router.push({
name: 'Detail', // 路由配置里的 name 字段
params: { id: 30 }
})
// 路由 path: '/detail/:id' → 最终地址 /detail/30
重点:params 传参只能 name,禁止 path。
4.4 写法 4:name+params+query混用(两种参数同时携带)
router.push({
name: 'Detail',
params: { id: 40 },
query: { type: 'goods' }
})
// 地址:/detail/40?type=goods
4.5 配套 replace 写法
replace 和 push 格式一模一样,仅替换历史记录:
// 所有 push 的参数原样丢进 replace 即可
router.replace({ name: 'Detail', params: { id: 50 } })
5. 重定向 (redirect) VS 转发 (forward)
5.1 转发 forward(一次请求,地址栏不变)
- 用户浏览器发 1 次请求访问
/xxx - 服务/路由内部悄悄从
xxx.vue→yyy.vue,服务器内部跳转 - 最终页面渲染 yyy 内容,但浏览器 URL 还是原来的
/xxx,地址栏不改动 - 只产生 1 次 HTTP 请求
- Vue 里没有原生 forward,后端 Java/Spring 常用,特点:地址不变、一次请求
5.2 重定向 redirect(两次请求,地址栏变新地址)
- 浏览器请求
/xxx - 后端返回响应,告诉浏览器:你去访问
/yyy - 浏览器收到指令,自动发起第二次全新请求访问
/yyy - 地址栏从
/xxx变成/yyy(URL 发生变化) - 一共 2 次网络请求
5.3 代码实战
路由配置重定向(路由规则里写 redirect):
const routes = [
// 访问 / 自动重定向到 /home,地址栏变成 /home
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home }
]
编程式重定向(和 replace 效果一致):
// 编程式重定向
router.replace('/home')
补充:forward 转发是后端服务端技术(Java Servlet、Spring):在服务器内部资源互换,不经过浏览器、不改 URL、一次请求。Vue 是前端 SPA 单页应用,页面都在浏览器,没有后端服务的容器环境,原生路由不支持服务端转发。
6. 如何解决重复提交问题
6.1 什么是重复提交问题
重复提交是指用户或系统不小心重复触发了同一个操作,可能会导致结果不正确或者数据重复。
常见场景:
- 重复扣款
- 重复下单
- 数据库中插入多条重复记录
6.2 什么是幂等性(Idempotency)
幂等性是一个操作被执行一次或执行多次,结果完全一样。
示例:
- 查询账户余额:你点一次还是点 100 次,结果都是当前余额,不会增加或减少。
- 修改用户名:你把用户名改为 “Alice”,多次执行操作,结果都是 “Alice”,不会重复增加用户名。
6.3 前端 Vue3 如何防止重复提交
方法一:按钮禁用
<template>
<button :disabled="loading" @click="submit">提交</button>
</template>
<script setup>
import { ref } from 'vue'
const loading = ref(false)
function submit() {
if (loading.value) return
// ========== 上锁在这里 ==========
loading.value = true
// 模拟请求
setTimeout(() => {
console.log('请求完成')
// ========== 解锁在这里 ==========
loading.value = false
}, 2000)
}
</script>
原理:
:disabled:禁用表单控件(按钮、输入框、下拉)- 静态(无
:):值写死字符串,变量改动页面不更新 - 动态(
:v-bind):绑定响应式数据,变量变化,标签属性自动变化
效果:用户点击一次,按钮禁用,防止重复提交。
方法二:前端去重 / 防抖
节流:1 秒内只放行第一次点击,剩下直接作废
// 全局变量:记录上一次成功提交的时间,初始=0
let lastTime = 0
function submit() {
// now = 当前点击的毫秒时间戳(13位数字)
const now = Date.now()
// 【核心判断】现在时间 - 上次提交时间 < 1000毫秒(1秒) → 直接return结束函数
if (now - lastTime < 1000) return
// 能走到这里,说明间隔超过1秒,允许提交,更新上次提交时间为当前时间
lastTime = now
// 执行提交逻辑
console.log('执行提交')
}
防抖:
let timer = null // 存计时器钥匙,初始空
function submit() {
clearTimeout(timer) // 1. 来了新点击 → 废掉上一轮倒计时
timer = setTimeout(() => { // 2. 新建1秒倒计时
console.log('发请求')
}, 1000)
}
效果:用时间限制重复点击。
方法三:后端接口幂等
前端可能防不全,有些情况还是后端要保证幂等。
常用手段:
- 幂等 ID:每次请求生成唯一 ID,后端记录处理过的请求
- 唯一约束:数据库字段唯一索引
- 状态检查:判断操作是否已经完成
7. 总结
Vue Router 作为 Vue.js 官方路由解决方案,提供了丰富的功能和灵活的配置选项。本文涵盖了:
- params 传参:注意只能用 name 不能 path,且需提前在路由规则中占位
- push vs replace:push 追加历史,replace 替换历史
- $route vs $router:前者获取信息,后者控制跳转
- 编程式导航:多种写法灵活应对不同场景
- 重定向与转发:理解两者的本质区别
- 重复提交防护:前端按钮禁用、节流防抖,后端幂等设计
掌握这些核心概念和技巧,能够帮助开发者更好地使用 Vue Router 构建高效、稳定的单页面应用。
更多推荐


所有评论(0)