一、路由传值的核心方式与场景
定义:在Vue应用中,页面跳转时传递数据的机制,是单页应用(SPA)数据流通的重要方式。
核心场景:
- 详情页传递资源ID(如商品详情页传商品ID);
- 列表页传递筛选条件(如搜索关键词、页码);
- 跨页面传递临时状态(如表单填写进度)。
二、URL 传值(最常用方案)
1. 路径参数(Path Parameters)
- 配置与传值:
// 路由配置(定义参数) const routes = [ { path: '/user/:id', component: UserDetail } ] // 编程式导航传值 this.$router.push('/user/123') // URL变为 /user/123 // 声明式导航传值 <router-link to="/user/123">用户详情</router-link>
- 接收参数:
// 组件中获取参数 const userId = this.$route.params.id // userId = '123' // Vue 3 组合式API import { useRoute } from 'vue-router' const route = useRoute() const userId = route.params.id
- 特点:
- 参数显示在URL中,刷新页面不丢失;
- 适合传递标识性数据(如ID、类型),参数结构固定。
2. 查询参数(Query Parameters)
- 配置与传值:
// 编程式导航 this.$router.push({ path: '/search', query: { keyword: 'apple', page: 1 } }) // URL变为 /search?keyword=apple&page=1 // 声明式导航 <router-link :to="{ path: '/search', query: { keyword: 'apple' }}">搜索</router-link>
- 接收参数:
const keyword = this.$route.query.keyword // 'apple' const page = Number(this.$route.query.page) // 1
- 特点:
- 参数显示在URL中,适合传递非标识性数据(如搜索条件、分页参数);
- 支持更灵活的参数结构(如对象、数组,但需JSON序列化)。
三、编程式传值(state 传值)
- 传值方式:
// 跳转时传递state(数据不显示在URL中) this.$router.push({ name: 'User', params: { id: 123 }, state: { from: 'home', data: { foo: 'bar' } } }) // 命名路由传值(更推荐) this.$router.push({ name: 'UserDetail', params: { id: 123 }, state: { from: 'home' } })
- 接收参数:
// 仅在同一路由跳转时有效(如从A→B→A) const from = this.$route.state.from // 'home' // 注意:刷新页面会丢失state数据
- 局限性:
- 兼容性差(部分浏览器不支持);
- 仅适用于临时状态传递,不推荐作为主要方案。
四、非URL传值方案(复杂场景)
1. Vuex/Pinia 状态管理
- 适用场景:跨页面、跨组件的大量数据传递(如用户信息、购物车)。
- 示例:
// 存储数据到Vuex store.commit('setProduct', { id: 123, name: '手机' }) // 跳转页面 this.$router.push('/product/detail') // 接收数据 const product = this.$store.state.product
2. 本地存储(localStorage/sessionStorage)
- 适用场景:传递大量数据或需要刷新保留的数据(如表单草稿)。
- 示例:
// 存储数据 localStorage.setItem('formData', JSON.stringify({ name: '小明', age: 18 })) // 跳转页面 this.$router.push('/form/submit') // 接收数据 const formData = JSON.parse(localStorage.getItem('formData'))
- 注意:需手动管理数据生命周期,避免内存泄漏。
3. 事件总线(EventBus)
- 适用场景:简单场景下的跨页面通信(如登录成功后刷新用户信息)。
- 示例:
// 事件总线 import { ref } from 'vue' export const eventBus = ref({}) // 发送数据 eventBus.value.emit('update-user', { id: 123 }) // 接收数据 eventBus.value.on('update-user', (data) => { this.userId = data.id })
五、问题
1. 问:路径参数和查询参数的本质区别?
- 答:
- URL结构:路径参数嵌入路径(如
/user/123
),查询参数附加在URL后(如?id=123
); - 语义化:路径参数更符合RESTful规范(标识资源),查询参数表示资源的筛选条件;
- 参数限制:路径参数通常为字符串,查询参数可通过编码传递复杂数据(如JSON)。
- URL结构:路径参数嵌入路径(如
2. 问:如何传递复杂对象数据?
- 答:
- URL传值:需先序列化对象(如
JSON.stringify
),接收时再解析:// 传值 const params = { id: 123, options: { color: 'red' } } this.$router.push({ path: '/page', query: { data: JSON.stringify(params) } }) // 取值 const data = JSON.parse(this.$route.query.data)
- 非URL方案:使用Vuex或本地存储传递,避免URL长度限制(浏览器通常限制URL长度在2KB以内)。
- URL传值:需先序列化对象(如
3. 问:路由传值时中文乱码如何解决?
- 答:
- 编码处理:传值时用
encodeURIComponent
编码,取值时用decodeURIComponent
解码:// 传值 const keyword = '苹果'; this.$router.push(`/search?keyword=${encodeURIComponent(keyword)}`); // 取值 const decodedKeyword = decodeURIComponent(this.$route.query.keyword);
- 服务器配置:确保后端接口和服务器支持UTF-8编码(如Nginx添加
charset utf-8
)。
- 编码处理:传值时用
六、传值方案对比与最佳实践
方案 | 优点 | 缺点 | 推荐场景 |
---|---|---|---|
路径参数 | URL语义化,刷新保留 | 参数结构固定,不适合复杂数据 | 详情页ID、分类导航 |
查询参数 | 灵活支持多参数,刷新保留 | URL可能过长,中文需编码 | 搜索条件、分页、筛选器 |
state 传值 | 数据不暴露在URL中 | 刷新丢失,兼容性差 | 临时状态(如跳转来源页面) |
Vuex/Pinia | 适合大量数据,跨组件共享 | 引入状态管理复杂度 | 大型应用、全局数据共享 |
本地存储 | 可存储大量数据,刷新不丢失 | 数据需手动清理,可能过期 | 临时草稿、跨页面缓存 |