Uniapp 中根据不同离开页面方式处理 onHide
的方法
在 Uniapp 开发中,onHide
生命周期会在页面隐藏时触发,但默认无法直接区分用户是通过何种方式离开页面的。不过我们可以通过组合其他钩子函数和路由事件来实现对不同离开方式的识别和处理。
一、常见的页面离开方式
路由跳转
- 使用
uni.navigateTo
跳转到非 tab 页面 - 使用
uni.switchTab
跳转到 tab 页面 - 使用
uni.redirectTo
重定向到其他页面 - 使用
uni.reLaunch
关闭所有页面并跳转
- 使用
返回操作
- 点击手机物理返回键
- 点击页面中的返回按钮(如
uni.navigateBack
) - 小程序左上角的导航栏返回按钮
其他场景
- 小程序被切入后台(
onHide
会触发) - 页面被组件覆盖(如弹窗、模态框)
- 小程序被切入后台(
二、区分离开方式的实现方法
1. 通过路由参数标记跳转方式
export default {
data() {
return {
leaveType: '' // 记录离开方式
}
},
onLoad(options) {
// 从参数中获取离开方式标记
if (options.leaveType) {
this.leaveType = options.leaveType;
}
},
onHide() {
this.handleLeavePage();
},
methods: {
// 处理不同离开方式
handleLeavePage() {
switch (this.leaveType) {
case 'navigateTo':
console.log('通过 navigateTo 离开');
// 保存临时数据
break;
case 'switchTab':
console.log('切换到 Tab 页面');
// 暂停定时器
break;
case 'navigateBack':
console.log('返回上一页');
// 提交未保存数据
break;
default:
console.log('未知方式离开');
}
},
// 页面内按钮跳转示例
goToNextPage() {
uni.navigateTo({
url: '/pages/next-page',
// 携带离开方式标记
events: {
// 可接收目标页面返回的数据
},
success: (res) => {
// 跳转成功后执行
}
});
}
}
}
2. 使用全局状态管理(Vuex/Pinia)记录操作
// store/index.js (使用 Pinia)
import { defineStore } from 'pinia'
export const useAppStore = defineStore('app', {
state: () => ({
lastLeaveType: ''
}),
actions: {
setLeaveType(type) {
this.lastLeaveType = type;
}
}
})
// 页面中使用
<template>
<view>
<button @click="goBack">返回上一页</button>
<button @click="goToTab">切换到 Tab 页</button>
</view>
</template>
<script>
import { useAppStore } from '@/store'
export default {
setup() {
const appStore = useAppStore();
const goBack = () => {
appStore.setLeaveType('navigateBack');
uni.navigateBack();
}
const goToTab = () => {
appStore.setLeaveType('switchTab');
uni.switchTab({ url: '/pages/tab/index' });
}
return {
goBack,
goToTab
}
},
onHide() {
const leaveType = appStore.lastLeaveType;
if (leaveType === 'navigateBack') {
// 处理返回操作
} else if (leaveType === 'switchTab') {
// 处理切换 Tab 操作
}
}
}
</script>
3. 监听物理返回键和导航栏返回事件
export default {
data() {
return {
isBackAction: false,
isTabSwitch: false
}
},
onLoad() {
// 监听物理返回键
uni.onBackPress(() => {
this.isBackAction = true;
// 这里可以控制是否允许返回
return false; // 阻止默认返回行为
});
// 监听页面切换到 Tab 的事件(需要配合全局监听)
// 可在 App.vue 中监听 tab 切换
},
onShow() {
// 每次显示时重置标记
this.isBackAction = false;
this.isTabSwitch = false;
},
onHide() {
if (this.isBackAction) {
console.log('用户点击了返回按钮');
this.saveBeforeBack();
} else if (this.isTabSwitch) {
console.log('切换到了 Tab 页面');
this.pauseProcess();
} else {
console.log('其他方式离开页面');
}
},
methods: {
// 跳转到非 Tab 页面
goToOtherPage() {
uni.navigateTo({ url: '/pages/other' });
},
// 切换到 Tab 页面(需在 App.vue 中标记)
switchToTab() {
getApp().globalData.isTabSwitch = true;
uni.switchTab({ url: '/pages/tab/index' });
}
}
}
4. 在 App.vue 中全局监听路由事件
// App.vue
export default {
onLaunch() {
console.log('App Launch');
this.globalData = {
lastRouteAction: '' // 记录最后一次路由操作
}
// 监听路由变化
uni.onAppRoute((obj) => {
const { path, query } = obj;
// 判断路由操作类型
if (path.startsWith('/pages/tab/')) {
this.globalData.lastRouteAction = 'switchTab';
} else if (query._navigateBack) {
this.globalData.lastRouteAction = 'navigateBack';
} else {
this.globalData.lastRouteAction = 'navigateTo';
}
});
},
onShow() {
console.log('App Show');
},
onHide() {
console.log('App Hide');
}
}
// 页面中使用
export default {
onHide() {
const lastAction = getApp().globalData.lastRouteAction;
switch (lastAction) {
case 'switchTab':
// 处理 Tab 切换
break;
case 'navigateBack':
// 处理返回
break;
case 'navigateTo':
// 处理普通跳转
break;
}
}
}
三、不同场景的处理建议
离开方式 | 检测方法 | 典型处理场景 |
---|---|---|
普通跳转(navigateTo) | 通过路由参数或全局状态标记 | 保存临时表单数据、暂停非紧急任务 |
返回(navigateBack) | 监听物理返回键或路由参数 | 提交未保存内容、提示用户确认离开 |
切换 Tab(switchTab) | 全局监听或在跳转时标记 | 暂停实时数据更新、保存页面滚动位置 |
小程序切后台 | 结合 onHide 和 onAppHide 事件 | 暂停音频播放、保存当前操作进度 |
重定向(redirectTo) | 通过路由参数或全局状态标记 | 清除临时缓存、释放资源 |
四、最佳实践
组合使用多种检测方法:根据项目复杂度选择合适的检测方式,复杂场景可结合全局状态和路由参数
避免过度标记:只对关键操作进行标记,避免增加过多代码复杂度
重置状态:在
onShow
中重置标记状态,确保每次页面显示时状态干净性能考虑:避免在
onHide
中执行耗时操作,优先使用异步处理或标记待处理任务
export default {
onHide() {
// 标记需要处理的任务,而非直接执行
this.pendingTasks = {
saveData: true,
pauseTimer: true
};
},
onUnload() {
// 页面卸载时执行最终处理
if (this.pendingTasks.saveData) {
this.saveAllData();
}
}
}
通过以上方法,你可以在 onHide
中区分不同的离开方式,并执行针对性的处理逻辑,提升用户体验和应用稳定性。