5步完成Ionic跨平台应用部署:从Web到原生移动端完整指南
2026/7/12 17:18:05
在一个审批小程序中,用户操作流程如下:
问题:返回列表后,该申请仍显示"草稿"状态,而不是"待审批"状态。用户需要手动下拉刷新才能看到最新状态。
操作流程: 列表页(草稿) → 详情页 → 编辑页 → 提交成功 → 返回列表页 ↓ 期望:显示"待审批" ✅ 实际:显示"草稿" ❌小程序使用页面栈管理页面:
navigateTo 进入新页面: ┌─────────────────┐ │ 编辑页 (栈顶) │ ← 当前显示 ├─────────────────┤ │ 详情页 │ ├─────────────────┤ │ 列表页 (栈底) │ ← 保持状态,不销毁 └─────────────────┘ navigateBack 返回: ┌─────────────────┐ │ 详情页 (栈顶) │ ← 当前显示,从缓存恢复 ├─────────────────┤ │ 列表页 │ └─────────────────┘| 操作 | onLoad | onShow | onHide | onUnload |
|---|---|---|---|---|
| navigateTo 进入 | ✅ | ✅ | - | - |
| navigateBack 返回 | ❌ | ✅ | - | ✅(被返回的页面) |
| switchTab 切换 | 首次✅ | ✅ | ✅ | - |
关键点:navigateBack返回时,不会触发onLoad,只触发onShow。
如果列表页的数据加载逻辑只写在onLoad中:
// ❌ 问题代码onLoad(){this.loadList()// 只在首次进入时执行}返回时就不会刷新数据。
// 列表页exportdefault{data(){return{list:[]}},onShow(){// 每次页面显示都刷新this.loadList()},methods:{asyncloadList(){constres=awaitapi.getApprovalList()this.list=res.data}}}优点:
缺点:
适用场景:数据变化频繁、列表数据量小、对实时性要求高
使用 uni-app 的事件机制,在数据变化时通知列表页刷新。
// 编辑页 - 提交成功后发送事件consthandleSubmit=async()=>{try{awaitapi.submitApproval(form)uni.showToast({title:'提交成功'})// 发送刷新事件uni.$emit('approval-list-refresh')// 返回上一页setTimeout(()=>{uni.navigateBack()},1500)}catch(e){uni.showToast({title:'提交失败',icon:'none'})}}// 列表页 - 监听事件exportdefault{onLoad(){this.loadList()// 监听刷新事件uni.$on('approval-list-refresh',this.loadList)},onUnload(){// 页面销毁时取消监听,防止内存泄漏uni.$off('approval-list-refresh',this.loadList)},methods:{asyncloadList(){constres=awaitapi.getApprovalList()this.list=res.data}}}优点:
缺点:
适用场景:大多数场景,推荐使用
使用全局变量标记是否需要刷新。
// 编辑页 - 设置刷新标记consthandleSubmit=async()=>{awaitapi.submitApproval(form)// 设置全局刷新标记getApp().globalData.needRefreshApprovalList=trueuni.navigateBack()}// 列表页 - 检查并处理刷新标记exportdefault{onLoad(){this.loadList()},onShow(){// 检查是否需要刷新if(getApp().globalData.needRefreshApprovalList){this.loadList()// 重置标记getApp().globalData.needRefreshApprovalList=false}},methods:{asyncloadList(){constres=awaitapi.getApprovalList()this.list=res.data}}}优点:
缺点:
适用场景:简单项目、少量页面间通信
返回时通过获取页面栈,直接调用上一页的方法。
// 编辑页 - 提交后通知上一页consthandleSubmit=async()=>{awaitapi.submitApproval(form)// 获取页面栈constpages=getCurrentPages()// 获取上一页(列表页)constprevPage=pages[pages.length-2]if(prevPage){// 直接调用上一页的方法prevPage.$vm.loadList()// 或者设置数据// prevPage.$vm.needRefresh = true}uni.navigateBack()}// 列表页 - 暴露刷新方法exportdefault{methods:{loadList(){// 供其他页面调用api.getApprovalList().then(res=>{this.list=res.data})}}}优点:
缺点:
适用场景:页面层级固定、关系明确的场景
使用状态管理库统一管理数据。
// store/approval.jsimport{defineStore}from'pinia'exportconstuseApprovalStore=defineStore('approval',{state:()=>({list:[],loading:false}),actions:{asyncfetchList(){this.loading=truetry{constres=awaitapi.getApprovalList()this.list=res.data}finally{this.loading=false}},asyncsubmitApproval(data){awaitapi.submitApproval(data)// 提交后自动刷新列表awaitthis.fetchList()}}})<!-- 列表页 --> <template> <view v-for="item in approvalStore.list" :key="item.id"> {{ item.title }} </view> </template> <script setup> import { useApprovalStore } from '@/store/approval' const approvalStore = useApprovalStore() onMounted(() => { approvalStore.fetchList() }) </script><!-- 编辑页 --> <script setup> import { useApprovalStore } from '@/store/approval' const approvalStore = useApprovalStore() const handleSubmit = async () => { await approvalStore.submitApproval(form) // store 内部已经刷新了列表 uni.navigateBack() } </script>优点:
缺点:
适用场景:大型项目、数据共享复杂的场景
| 方案 | 实现难度 | 性能 | 解耦程度 | 适用场景 |
|---|---|---|---|---|
| onShow 刷新 | ⭐ | ⭐⭐ | ⭐⭐⭐ | 数据实时性要求高 |
| 事件总线 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 大多数场景(推荐) |
| 全局标记 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | 简单项目 |
| 页面栈操作 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ | 层级固定的场景 |
| 状态管理 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 大型项目 |
// hooks/usePageRefresh.jsimport{onUnmounted}from'vue'/** * 页面刷新 Hook * @param {string} eventName 事件名 * @param {Function} callback 刷新回调 */exportconstusePageRefresh=(eventName,callback)=>{// 监听刷新事件uni.$on(eventName,callback)// 组件卸载时取消监听onUnmounted(()=>{uni.$off(eventName,callback)})// 返回触发刷新的方法return{triggerRefresh:()=>uni.$emit(eventName)}}使用:
// 列表页import{usePageRefresh}from'@/hooks/usePageRefresh'constloadList=async()=>{list.value=awaitapi.getList()}// 监听刷新usePageRefresh('approval-refresh',loadList)onMounted(loadList)// 编辑页import{usePageRefresh}from'@/hooks/usePageRefresh'const{triggerRefresh}=usePageRefresh('approval-refresh')consthandleSubmit=async()=>{awaitapi.submit(form)triggerRefresh()// 触发列表刷新uni.navigateBack()}// constants/events.jsexportconstPAGE_EVENTS={// 审批模块APPROVAL_LIST_REFRESH:'approval:list:refresh',APPROVAL_DETAIL_UPDATE:'approval:detail:update',// 用户模块USER_INFO_UPDATE:'user:info:update',// 通用GLOBAL_REFRESH:'global:refresh'}// 使用import{PAGE_EVENTS}from'@/constants/events'uni.$emit(PAGE_EVENTS.APPROVAL_LIST_REFRESH)uni.$on(PAGE_EVENTS.APPROVAL_LIST_REFRESH,callback)// 编辑页 - 带参数触发uni.$emit('approval-refresh',{type:'update',id:this.approvalId,newStatus:'pending'})// 列表页 - 接收参数uni.$on('approval-refresh',(payload)=>{if(payload.type==='update'){// 局部更新,性能更好constitem=this.list.find(i=>i.id===payload.id)if(item){item.status=payload.newStatus}}else{// 全量刷新this.loadList()}})问题根因:navigateBack返回时不触发onLoad,只触发onShow
推荐方案:
注意事项:
onUnload中取消,防止内存泄漏核心原则:
谁修改数据,谁负责通知刷新
页面返回刷新是小程序开发中的高频问题,选择合适的方案可以让代码更清晰、更易维护。