onShow中拉取数据是实现“返回即刷新”的最直接方案,因其每次页面显示都会执行;需注意避免重复请求、重置分页状态,并可通过事件总线或跳转参数实现条件刷新。
onShow 里重新拉数据是最直接的方案
uni-app 的页面生命周期里,onload 只在首次进入时触发,而 onshow 每次页面显示都会执行——包括从下一页返回时。这是实现“返回即刷新”的底层依据。
常见错误是只在 onLoad 里请求接口,导致返回后数据还是旧的;或者误用 onReady(DOM 渲染完成但不保证页面可见)。
- 把数据获取逻辑从
onLoad搬到onShow中 - 如果需要避免首次进入时重复请求(比如
onLoad已经拉过),可用标志位控制:dataLoaded初始为false,onLoad设为true,onShow里只在!this.dataLoaded时再拉 - 注意:若页面有下拉刷新或分页,
onShow触发时应重置分页状态(如this.page = 1),否则可能漏数据
使用 $refs 或事件总线主动通知上一页刷新
当返回动作由自定义按钮(而非原生导航栏返回)触发,且你希望精确控制刷新时机,就不能依赖 onShow 的被动响应。
典型场景:列表页 → 详情页 → 编辑后保存 → 返回列表页并刷新。此时详情页知道“改完了”,该主动告诉列表页“请更新”。
- 在列表页
onLoad中用uni.$on('refreshList')订阅事件 - 在详情页保存成功后,调用
uni.$emit('refreshList') - 避免内存泄漏:列表页
onUnload里必须调用uni.$off('refreshList') - 不推荐用
getCurrentPages()手动取上一页实例再调方法——耦合高、易出错,且 H5 和小程序行为不一致
uni.navigateBack 后手动触发 onShow 失效?检查页面栈和缓存
有时写了 onShow 却没执行,大概率是页面被缓存了,或者没真正“返回”而是跳转到了新实例。
常见错误现象:console.log 在 onShow 里没输出,但页面明明显示出来了。
- 确认是否启用了
navigationStyle: custom并屏蔽了原生返回,却忘了在自定义按钮里调用uni.navigateBack() - 检查
pages.json中该页面是否配置了"enablePullDownRefresh": true—— 某些旧版 uni-app 在开启下拉刷新时会干扰onShow触发 - 真机调试时,iOS 微信环境可能因 WebView 缓存导致
onShow延迟或丢失,加个setTimeout容错不是好办法,优先确保页面没被keep-alive错误包裹(uni-app 默认不支持 Vue 的keep-alive,但自定义组件里误用会导致问题)
条件刷新:只在特定操作后才刷新,避免无意义请求
不是每次返回都要刷新。比如从搜索页返回列表页,应该保留原搜索结果;但从编辑页返回,才需要重载。
关键在于传递“是否需要刷新”的信号,而不是让所有返回都变重。
- 跳转时带参数:
uni.navigateTo({ url: '/pages/detail/detail?id=123&refresh=true' }),返回后在onShow里读options.refresh决定是否拉数据 - 用
uni.setStorageSync存临时标记(如uni.setStorageSync('shouldRefreshList', true)),列表页onShow读取后立即清除 - 慎用全局变量(如挂到
Vue.prototype或uni对象上)——多页面并发时容易污染
最麻烦的其实是跨端一致性:App 端 onShow 最可靠,H5 端可能受浏览器前进/后退缓存影响,微信小程序则对页面栈更敏感。别指望一套代码零适配跑通所有平台,得留一手兜底逻辑。

















