在 uni-app 开发中,页面传参是日常开发里非常高频的操作。无论是列表跳详情、表单回填,还是跨页面通信,都离不开参数传递。面试中,这道题往往不只是考察“你会不会用”,而是看你是否理解不同传参方式的底层机制、适用边界以及各自的坑。下面从实际开发视角,系统梳理 uni-app 中常见的页面传参方式。
一、URL 查询字符串传参
这是最基础、最常用的方式,本质上和传统 Web 的 ?key=value 一致。
使用方式:
// 传递
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=uniapp'
})
// 接收
onLoad(options) {
console.log(options.id) // '123'
console.log(options.name) // 'uniapp'
}
适用场景:
- 列表页跳转到详情页,传递商品 ID、文章 ID 等简单标识
- 页面间传递少量、简单的字符串或数字参数
- 需要分享链接或复制链接时,参数能直接体现在 URL 中
注意事项:
- 参数值必须进行
encodeURIComponent编码,否则遇到特殊字符(如&、=、中文)会解析错误 - 传递对象或数组时,需要先
JSON.stringify,接收后再JSON.parse - URL 长度有限制,参数过多或过大时不适合
- 参数会暴露在地址栏中,敏感信息不应通过此方式传递
编码示例:
const params = encodeURIComponent(JSON.stringify({ id: 1, list: [1,2] }))
uni.navigateTo({ url: `/pages/detail/detail?data=${params}` })
// 接收
onLoad(options) {
const data = JSON.parse(decodeURIComponent(options.data))
}
二、eventChannel 事件通道传参
eventChannel 是 uni-app 提供的一种页面间通信机制,适用于需要双向通信或传递复杂数据的场景。
使用方式:
// 页面 A:跳转并监听
uni.navigateTo({
url: '/pages/detail/detail',
success: (res) => {
res.eventChannel.emit('sendData', { id: 1, name: 'uniapp' })
}
})
// 页面 B:接收
onLoad() {
const eventChannel = this.getOpenerEventChannel()
eventChannel.on('sendData', (data) => {
console.log(data)
})
}
适用场景:
- 需要传递对象、数组等复杂数据结构,且不想手动序列化
- 子页面需要向父页面回传数据(如选择地址后返回)
- 页面间需要多次通信,而非一次性传参
注意事项:
- 只能通过
navigateTo打开页面时使用,redirectTo、switchTab不支持 - 页面 B 必须是通过
navigateTo打开的,否则getOpenerEventChannel获取不到 - 事件通道是单向的,父页面监听子页面 emit 的事件需要额外处理
回传数据示例:
// 页面 B 回传
const eventChannel = this.getOpenerEventChannel()
eventChannel.emit('backData', { address: '北京市' })
// 页面 A 监听
uni.navigateTo({
url: '/pages/address/address',
events: {
backData: (data) => {
console.log(data.address)
}
}
})
三、全局变量 / 全局状态管理传参
通过 getApp().globalData 或 Vuex / Pinia 等状态管理工具,在全局共享数据。
使用方式:
// main.js 或 App.vue 中定义
globalData: {
userInfo: null
}
// 页面 A:赋值
getApp().globalData.userInfo = { name: 'uniapp' }
// 页面 B:读取
const userInfo = getApp().globalData.userInfo
适用场景:
- 多个页面都需要使用的数据,如用户登录信息、主题配置
- 参数数据量大,不适合放在 URL 中
- 跨页面、跨层级的复杂状态共享
注意事项:
- 全局变量是响应式的吗?
globalData本身不是响应式的,需要配合 Vuex/Pinia 才能实现响应式更新 - 数据不会自动清理,页面销毁后仍存在,需手动管理
- 不适合临时性、一次性的传参,容易造成数据污染
四、本地存储传参
通过 uni.setStorageSync / uni.getStorageSync 在本地缓存中存取数据。
使用方式:
// 页面 A:存储
uni.setStorageSync('tempData', { id: 1, name: 'uniapp' })
// 页面 B:读取
const data = uni.getStorageSync('tempData')
uni.removeStorageSync('tempData') // 用完清理
适用场景:
- 需要持久化保存的数据,如草稿、历史记录
- 参数较大,URL 无法承载
- 页面刷新或应用重启后仍需保留的数据
注意事项:
- 存储有容量限制(通常 10MB 左右)
- 同步操作可能阻塞主线程,大数据量建议用异步 API
- 需要手动清理,否则会造成缓存堆积
五、Vuex / Pinia 状态管理传参
在 uni-app 中使用 Vuex 或 Pinia,通过 store 共享状态。
使用方式:
// store 中定义
state: { orderInfo: {} }
mutations: { setOrderInfo(state, payload) { state.orderInfo = payload } }
// 页面 A
this.$store.commit('setOrderInfo', { id: 1 })
// 页面 B
this.$store.state.orderInfo
适用场景:
- 中大型项目中多个页面共享复杂状态
- 需要响应式更新、派生状态、模块化管理
- 参数需要在多个页面间保持同步
注意事项:
- 需要引入并配置 Vuex/Pinia,有一定学习成本
- 状态在页面刷新后会丢失(除非配合持久化插件)
- 不适合简单的临时传参,容易过度设计
六、各方式对比与选型建议
| 传参方式 | 数据量 | 复杂度 | 生命周期 | 适用场景 |
|---|---|---|---|---|
| URL 查询字符串 | 小 | 简单 | 页面级 | 列表跳详情、简单标识 |
| eventChannel | 中 | 中等 | 页面级 | 复杂对象、双向通信 |
| 全局变量 | 大 | 简单 | 应用级 | 用户信息、全局配置 |
| 本地存储 | 大 | 简单 | 持久化 | 草稿、历史记录 |
| Vuex/Pinia | 大 | 复杂 | 应用级 | 中大型项目状态共享 |
选型原则:
- 简单优先:能用 URL 传参就用 URL,不要过度设计
- 数据量决定方式:小数据用 URL,大数据用全局或存储
- 生命周期决定方式:临时数据用 eventChannel,持久数据用存储
- 项目规模决定方式:小型项目用 globalData,中大型项目用 Vuex/Pinia
七、面试加分点
回答这道题时,如果能补充以下内容,会显得更有深度:
- URL 传参的编码问题:为什么需要
encodeURIComponent,不编码会怎样 - eventChannel 的局限性:为什么
redirectTo不能用,底层原理是什么 - globalData 的非响应式问题:如何配合 Vuex 实现响应式
- 各端的差异:小程序端 URL 长度限制、本地存储容量限制等
- 实际踩坑经验:如 URL 传对象时
JSON.stringify后仍可能因特殊字符出错
总结
uni-app 页面传参没有“万能方案”,关键是理解每种方式的机制和边界。URL 传参适合简单场景,eventChannel 适合复杂对象和双向通信,全局变量和状态管理适合跨页面共享,本地存储适合持久化。实际开发中,往往是多种方式组合使用。面试时,除了列出方式,更要讲清楚“为什么选它”和“什么时候不选它”,这才是区分初级和高级开发者的关键。
未经允许不得转载:任鹏个人博客 » uni-app 中页面传参有哪些方式?各自适用什么场景?

