在 uniapp 中,页面生命周期方法 onShow
通常用于页面重新显示时更新数据,例如从详情页返回列表页时刷新数据。然而,如果处理不当,可能会导致数据重复加载、请求过多或刷新时机不精准的问题。
本文将详细介绍如何结合事件机制(如 uni.$emit
/ uni.$on
)和 onShow
生命周期,精准触发刷新,防止重复加载。
一、常见问题场景
- 重复请求
- 从列表页进入详情页再返回时,如果
onShow
直接调用getList()
,每次返回都会重复请求。 - 如果多次绑定
uni.$on
事件,没有解绑,事件会累积触发多次。
- 刷新不精准
- 仅需要在特定情况下刷新数据(如保存了新记录、修改了状态),但
onShow
无条件刷新,增加不必要的开销。
二、基本用法回顾
onShow
的特性
- 每次页面显示时都会触发,包括:
- 从其他页面返回
- 从后台进入前台
- 执行时机在
onLoad
之后,且不重新创建页面实例
常见问题示例(容易导致重复请求)
export default {onShow() {// 直接请求接口this.getList();},methods: {getList() {console.log('请求数据');}}
}
这种写法,每次返回页面都会触发一次,且无法控制是否需要刷新。
三、配合 uni.$emit
与 uni.$on
精准刷新
思路
- 详情页完成新增/修改/删除后,调用
uni.$emit('refresh', { refresh: true })
通知列表页 - 列表页在
onShow
中只监听事件,不直接刷新 - 根据事件参数判断是否需要刷新,并在刷新后解除事件监听
列表页(接收刷新信号)
export default {onShow() {// 防止重复绑定uni.$off('refresh');uni.$on('refresh', (data) => {if (data && data.refresh) {console.log('收到刷新信号,开始更新数据');this.getList();}});},onUnload() {// 页面卸载时解绑,防止内存泄漏uni.$off('refresh');},methods: {getList() {console.log('请求数据...');// 这里执行接口请求逻辑}}
}
详情页(发送刷新信号)
export default {methods: {saveData() {// 保存成功后通知列表刷新uni.$emit('refresh', { refresh: true });// 返回上一页uni.navigateBack();}}
}
四、防止事件累积触发的关键点
uni.$off()
清理旧事件
- 每次
onShow
前先解绑同名事件,防止重复绑定
onUnload
中解绑
- 页面被销毁时清理事件,避免内存泄漏
- 按需刷新
- 通过事件参数判断是否真的需要刷新
五、结合防抖进一步优化
如果某些情况会短时间内触发多次刷新,可以使用防抖函数:
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}export default {onShow() {uni.$off('refresh');uni.$on('refresh', debounce((data) => {if (data.refresh) {this.getList();}}, 300));}
}
这样可避免多次触发短时间内的重复请求。
六、总结
onShow
默认刷新容易导致重复加载,需配合事件机制控制刷新时机- 使用
uni.$emit
+uni.$on
可以精准定位需要刷新的时刻 - 每次监听前先
uni.$off
,防止重复绑定 - 页面销毁时记得解绑事件,避免内存泄漏
- 可结合防抖优化,减少接口压力
通过以上方式,可以让 onShow
配合 refresh
信号实现数据精准刷新,既避免了重复请求,又保证了数据的实时性。