UniApp 页面传参方式详解
在 UniApp 开发中,页面间参数传递是核心功能之一。以下是 8 种常用的传参方式,每种方式都有其适用场景和特点:
一、URL 拼接传参(最常用)
适用场景:简单数据传递,如 ID、状态值等基础类型数据
实现方式:
// 发送参数
uni.navigateTo({url: '/pages/detail/detail?id=123&name=张三'
})// 接收参数(在目标页面的 onLoad 生命周期中获取)
export default {onLoad(options) {console.log(options.id) // 123console.log(options.name) // "张三"}
}
特点:
- 参数自动解析为字符串
- 长度受限(URL 最大长度约 2KB)
- 不支持复杂对象(需手动序列化)
二、全局变量传参
适用场景:跨页面共享数据(如用户信息)
实现方式:
// app.vue 中定义全局变量
export default {globalData: {userInfo: null}
}// 页面 A 设置数据
const app = getApp()
app.globalData.userInfo = { id: 1, name: '张三' }// 页面 B 读取数据
const app = getApp()
console.log(app.globalData.userInfo)
特点:
- 适合共享频繁使用的数据
- 非响应式(需配合事件机制)
- 长期存在可能内存泄漏
三、Vuex 状态管理
适用场景:复杂应用状态共享
实现方式:
// store.js
export default new Vuex.Store({state: {cartItems: []},mutations: {addToCart(state, item) {state.cartItems.push(item)}}
})// 页面 A 提交数据
this.$store.commit('addToCart', { id: 101, name: '商品A' })// 页面 B 获取数据
computed: {cartItems() {return this.$store.state.cartItems}
}
特点:
- 响应式数据流
- 支持调试工具
- 适合中大型项目
四、本地存储传参
适用场景:持久化数据传递(如登录状态)
实现方式:
// 页面 A 存储数据
uni.setStorageSync('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9')// 页面 B 读取数据
const token = uni.getStorageSync('token')
特点:
- 数据持久化(关闭应用仍存在)
- 同步操作可能阻塞渲染
- 容量限制(通常 5-10MB)
五、事件总线(EventBus)
适用场景:任意组件/页面间通信
实现方式:
// utils/eventBus.js
export default new Vue()// 页面 A 发送事件
import eventBus from '@/utils/eventBus'
eventBus.$emit('data-update', { newData: 42 })// 页面 B 监听事件
export default {onLoad() {eventBus.$on('data-update', data => {console.log('收到数据:', data)})},onUnload() {eventBus.$off('data-update') // 必须解绑!}
}
特点:
- 完全解耦的通信方式
- 需手动管理事件监听
- 滥用可能导致"事件地狱"
六、页面通信通道
适用场景:需要获取前序页面实例的场景
实现方式:
// 获取前序页面实例
const pages = getCurrentPages()
const prevPage = pages[pages.length - 2] // 上一页// 直接调用前页方法
prevPage.$vm.updateData({ id: 2024 })// 目标页面定义方法
methods: {updateData(data) {this.data = dataconsole.log('收到数据:', data)}
}
特点:
- 可直接操作页面实例
- 破坏封装性(慎用)
- 小程序端最多 10 层页面栈
七、URL 编码复杂对象
适用场景:需要传递 JSON 对象
实现方式:
// 发送复杂对象
const product = {id: 1001,name: '手机',specs: { color: '黑色', memory: '256GB' }
}uni.navigateTo({url: `/pages/detail/detail?data=${encodeURIComponent(JSON.stringify(product))}`
})// 接收端解析
onLoad(options) {const product = JSON.parse(decodeURIComponent(options.data))console.log(product.specs.color) // "黑色"
}
特点:
- 解决 URL 传对象问题
- 注意特殊字符编码
- 数据量受限
八、uni.emit和uni.emit 和 uni.emit和uni.on
适用场景:跨页面事件通信(UniApp 2.8.0+)
实现方式:
// 页面 A 发送事件
uni.$emit('update', { msg: '数据更新' })// 页面 B 监听事件
export default {onLoad() {uni.$on('update', this.handleUpdate)},methods: {handleUpdate(data) {console.log('收到更新:', data.msg)}},onUnload() {uni.$off('update', this.handleUpdate) // 必须解绑}
}
特点:
- 官方提供的全局事件机制
- 需手动管理事件绑定
- 适合简单通知类通信
最佳实践建议
- 简单数据传递:优先使用 URL 传参
- 用户状态管理:Vuex + 本地存储持久化
- 复杂对象传递:URL 编码或全局变量
- 跨级通信:EventBus 或 uni.$emit
- 重要数据传递:始终添加参数校验
// 参数校验示例
onLoad(options) {if (!options.id || isNaN(options.id)) {uni.showToast({ title: '参数错误', icon: 'error' })uni.navigateBack()return}
}
- 内存管理:在
onUnload
中清理资源
onUnload() {// 清除事件监听eventBus.$off('update')uni.$off('update')// 释放大对象this.largeData = null
}
性能优化技巧
- 大数据传递:使用 ID 传递,目标页面重新请求
- 频繁更新数据:使用 Vuex 响应式更新
- 页面返回刷新:
// 前页注册刷新方法
onShow() {if (this.$options.refreshData) {this.$options.refreshData()}
}// 后页触发刷新
const pages = getCurrentPages()
const prevPage = pages[pages.length - 2].$vm
prevPage.$options.refreshData = () => {console.log('执行刷新操作')
}
根据具体场景选择合适的传参方式,可以显著提升应用的可维护性和性能表现。