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
中區分不同的離開方式,并執行針對性的處理邏輯,提升用戶體驗和應用穩定性。