Uni-app 生命周期与钩子:程序的“生命”旅程
Uni-app 生命周期与钩子
- 一、应用生命周期 (App Lifecycle)
- onLaunch
- 什么时候触发?
- 常用场景?
- onShow
- 什么时候触发?
- 常用场景?
- onHide
- 什么时候触发?
- 常用场景?
- onError
- 什么时候触发?
- 常用场景?
- onPageNotFound
- 什么时候触发?
- 常用场景?
- onUnhandledRejection
- 什么时候触发?
- 常用场景?
- onThemeChange
- 什么时候触发?
- 常用场景?
- 二、页面生命周期 (Page Lifecycle)
- onLoad(options)
- 什么时候触发?
- 常用场景?
- onShow
- 什么时候触发?
- 常用场景?
- onReady
- 什么时候触发?
- 常用场景?
- onHide
- 什么时候触发?
- 常用场景?
- onUnload
- 什么时候触发?
- 常用场景?
- onPullDownRefresh
- 什么时候触发?
- 常用场景?
- onReachBottom
- 什么时候触发?
- 常用场景?
- onShareAppMessage(options)
- 什么时候触发?
- 常用场景?
- onShareTimeline()
- 什么时候触发?
- 常用场景?
- onPageScroll(object)
- 什么时候触发?
- 常用场景?
- onResize(object)
- 什么时候触发?
- 常用场景?
- onTabItemTap(object)
- 什么时候触发?
- 常用场景?
- onBackPress(options) (+uni.navigateBack)
- 什么时候触发?
- 常用场景?
- onNavigationBarButtonTap(object)
- 什么时候触发?
- 常用场景?
- 三、组件生命周期 (Component Lifecycle) - Vue 3 Composition API
- setup()
- 什么时候触发?
- 常用场景?
- onBeforeMount(() => { ... })
- 什么时候触发?
- 常用场景?
- onMounted(() => { ... })
- 什么时候触发?
- 常用场景?
- onBeforeUpdate(() => { ... })
- 什么时候触发?
- 常用场景?
- onUpdated(() => { ... })
- 什么时候触发?
- 常用场景?
- onBeforeUnmount(() => { ... })
- 什么时候触发?
- 常用场景?
- onUnmounted(() => { ... })
- 什么时候触发?
- 常用场景?
- onErrorCaptured((err, instance, info) => { ... })
- 什么时候触发?
- 常用场景?
你可以把一个 Uni-app 页面或组件想象成一个有生命的物体。从它被“出生”到“死亡”,会经历一系列重要的阶段,每个阶段都有一些特定的“事情”会发生。这些“事情”就是我们说的“生命周期钩子”(或者叫“生命周期函数”)。
通俗来说:生命周期钩子就是在页面或组件的特定时刻,你可以插入自己的代码来执行一些操作。
Uni-app 有两种主要的生命周期:
- 应用生命周期 (App Lifecycle): 整个小程序的生命。
- 页面生命周期 (Page Lifecycle): 某个“页面”的生命。
- 组件生命周期 (Component Lifecycle): 某个“组件”的生命(Vue3 Setup 风格下,组件生命周期和页面生命周期很多是共享的)。
一、应用生命周期 (App Lifecycle)
这指的是 整个 Uni-app 应用(小程序/H5/App) 的生命周期。它们在 App.vue 文件中定义。
onLaunch
什么时候触发?
最开始,App 第一次启动的时候。 整个应用只会触发一次。无论你从哪个页面进入、从小程序码、分享链接进入,都是第一次启动,就会调用。
常用场景?
- 获取用户信息或登录: 第一次启动时尝试静默登录,或者获取用户的基本信息(如 uni.login() 获取 code)。
- 全局配置初始化: 设置一些全局变量、主题配置等。
- 检查更新: 小程序如果有新版本,在这里提示用户。
- 加载全局数据: 比如从缓存中读取一些 App 级别的数据。
onShow
什么时候触发?
App 启动或从后台进入前台的时候。 比如你把小程序切到微信聊天界面,再切回来,就会触发。
常用场景?
- 统计用户活跃: 记录用户每次进入 App 的时间。
- 检查网络状态: 每次切回前台时,确保网络连接正常。
- 刷新数据: 如果你在后台修改了一些数据(比如个人信息),切回前台时可能需要刷新页面显示。
- 检查消息通知: 从后台切回时,检查是否有新的消息需要提示。
onHide
什么时候触发?
App 从前台进入后台的时候。 比如小程序切到微信聊天,或者点击了 Home 键。
常用场景?
- 保存数据: 用户离开时需要保存一些临时数据(如购物车状态、草稿)。
- 清除定时器: 停止一些不必要的后台运行,节省资源。
- 暂停音乐/视频播放。
onError
什么时候触发?
App 运行过程中发生错误的时候。 比如 JavaScript 运行时错误或网络请求失败。
常用场景?
- 错误监控和上报: 收集运行时的错误信息,发送到服务器进行分析和修复。
onPageNotFound
什么时候触发?
用户尝试打开一个不存在的页面路径。
常用场景?
- 自定义 404 页面: 可以重定向到首页或一个专门的错误页面,提升用户体验。
onUnhandledRejection
什么时候触发?
Promise 被拒绝,且没有 catch 处理器时触发。
常用场景?
- Promise 错误捕获: 统一处理 Promise 链中未被捕获的错误。
onThemeChange
什么时候触发?
用户切换主题时触发(深色模式/浅色模式)。仅微信小程序支持。
常用场景?
- 动态调整界面颜色: 根据用户选择的主题色,调整 App 的界面样式。
二、页面生命周期 (Page Lifecycle)
这指的是 某个具体页面 的生命周期。它们在每个 .vue 页面文件中定义(在 <script setup> 中直接导入或在 export default 中定义)。
onLoad(options)
什么时候触发?
页面第一次被加载的时候。 只会触发一次。options 里包含了页面跳转时传过来的参数(比如 uni.navigateTo({url: ‘/pages/detail?id=123’}),options.id 就是 123)。
常用场景?
- 获取页面参数: 读取传递到页面的数据,根据这些数据加载内容(比如商品详情页根据 ID 加载商品信息)。
- 一次性数据请求: 页面刚进来就需要的数据,而且不经常变化,只请求一次即可。
- 初始化页面状态: 设置页面标题、初始化表单数据等。
onShow
什么时候触发?
页面显示/活跃的时候。 每次进入页面(包括从其他页面回来、从后台切回前台)。
常用场景?
- 刷新数据: 最常用!比如从商品详情页返回列表页,需要刷新收藏状态;或者用户在其他地方修改了个人信息,回到个人中心需要刷新。
- 统计页面访问: 记录用户每次进入页面的行为。
- 清除定时器: 从后台切回页面时,可以恢复之前暂停的动画或定时器。
onReady
什么时候触发?
页面渲染完成的时候。 页面内容和组件都准备就绪,可以进行交互和操作了。
常用场景?
- 操作页面元素: 如果你需要获取页面上某个元素的高度、宽度,或者对 Canvas、Video 等组件进行操作,确保它们已经渲染完成。
- 启动动画: 在页面完全显示且稳定后,开始一些依赖布局的动画。
onHide
什么时候触发?
页面从前台进入后台的时候。 比如你从当前页面跳到另一个页面,或者把小程序/App 切到后台。
常用场景?
- 保存临时数据: 比如用户填写了一半的表单,可以暂时保存到缓存中,下次回来时恢复。这比在 onUnload 销毁前保存更安全。
- 停止不必要的活动: 比如停止视频播放、清除定时器、取消进行中的网络请求,避免资源浪费和性能问题。
onUnload
什么时候触发?
页面被销毁的时候。 比如用户点击返回按钮退出了这个页面,或者调用 uni.redirectTo、uni.reLaunch 跳转到其他页面时,当前页面就会被销毁。
常用场景?
- 清理资源: 清除所有监听器、定时器、WebSocket 连接等,防止内存泄漏。这是必须做的,确保程序干净地退出。
- 保存最终数据: 页面销毁前必须保存的数据(比如用户在当前页面完成的特定操作结果)。
onPullDownRefresh
什么时候触发?
用户下拉刷新页面的时候。 需要在 pages.json 或 uni.setNavigationBarTextStyle 中开启 “enablePullDownRefresh”: true。
常用场景?
- 刷新当前页面数据: 比如在商品列表页下拉刷新,重新请求商品数据。
- uni.stopPullDownRefresh(): 刷新完成后,一定要调用这个方法,否则加载动画会一直转。
onReachBottom
什么时候触发?
页面滚动到底部的时候。
常用场景?
- 加载更多数据: 比如在列表页滚动到底部时,加载下一页的内容(实现“上拉加载”)。
- 防止重复加载: 在请求数据时设置一个标志位,防止在数据还没回来时用户再次触发底部加载。
onShareAppMessage(options)
什么时候触发?
用户点击右上角菜单的“转发”按钮,或点击页面内 <button open-type=“share”></button> 按钮时触发。
常用场景?
- 自定义转发内容: 配置转发的标题、图片、路径等。可以根据 options.from 判断是“按钮”还是“菜单”触发的。必须返回一个对象,否则无法分享。
onShareTimeline()
什么时候触发?
用户点击右上角菜单的“分享到朋友圈”按钮时触发。仅微信小程序支持。
常用场景?
- 自定义分享朋友圈内容: 配置分享到朋友圈的标题、查询参数(不能有图片)。必须返回一个对象,否则无法分享。
onPageScroll(object)
什么时候触发?
页面滚动时触发。 object.scrollTop 表示当前滚动的距离。
常用场景?
- 吸顶效果: 根据滚动距离改变导航栏或某个组件的样式(比如固定在顶部)。
- 返回顶部按钮: 当滚动到一定距离时显示返回顶部按钮。
onResize(object)
什么时候触发?
页面尺寸改变时触发,比如横竖屏切换。App(含 H5)支持。小程序仅在 wx.onWindowResize 回调中返回。
常用场景?
- 响应式布局调整: 根据页面宽高调整布局或组件显示。
onTabItemTap(object)
什么时候触发?
点击 TabBar 上的某个 TabItem 时触发(即使当前就是该页)。object 包含当前 TabItem 的文本、索引、图标路径等信息。
常用场景?
- Tab 页面二次点击刷新: 当用户点击当前激活的 Tab 时,可以实现“点击两次刷新页面”的效果。
- Tab 切换统计。
onBackPress(options) (+uni.navigateBack)
什么时候触发?
用户点击左上角返回按钮,或者用手机自带的返回键返回时触发。在 options.from 为 backbutton 时才生效,其他情况会默认返回。仅 App 和 H5 支持。 微信小程序使用 uni.navigateBack 监听。
常用场景?
- 阻止返回: 当有重要操作未完成或表单未保存时,提示用户是否确定退出,避免数据丢失。
- 自定义返回行为: 不直接返回,而是跳转到其他页面。return true 可阻止默认返回行为。
onNavigationBarButtonTap(object)
什么时候触发?
点击页面右上角导航栏按钮时触发。这些按钮通过 pages.json navigationStyle: custom 或 `uni
常用场景?
- 添加/新建功能: 比如在列表页的右上角放置一个“+”号按钮,点击后跳转到新建页面。
- 筛选/排序: 在数据列表页右上角放置一个筛选或排序的图标,点击后弹出筛选条件。
- 分享/操作菜单: 放置一个三个点(更多)图标,点击后显示一个操作菜单。
- 自定义行为: 根据业务需求,在导航栏提供快速入口,执行特定的页面内操作。
三、组件生命周期 (Component Lifecycle) - Vue 3 Composition API
setup()
什么时候触发?
这是 script setup 模式的特殊处理。所有在 <script setup> 标签内直接声明的变量、函数、ref、reactive 以及执行的逻辑(不包括包裹在 onMounted 等钩子里的代码),都会在组件实例化时 同步执行。它发生在组件数据响应化处理之后,DOM 挂载之前。 相当于 Vue 2 的 beforeCreate 和 created 阶段的结合。
常用场景?
- 声明响应式状态: const count = ref(0);、const state = reactive({ name: ‘Vue’ });
- 定义计算属性和侦听器: const doubledCount = computed(() => count.value * 2);、watch(count, (newVal) => { … });
- 非 DOM 依赖的数据请求: 在组件渲染前就需要的初始化数据请求(如 uni.request),因为这些数据通常不需要等到 DOM 挂载。
- 注册非 DOM 相关事件监听器: 例如 uni.$on 发布的自定义事件。
onBeforeMount(() => { … })
什么时候触发?
组件的模板已经被编译成渲染函数,但尚未挂载到真实的 DOM 元素上。 此时可以访问到 ref 和 reactive 数据,但无法访问或操作真实的 DOM。
常用场景?
很少使用。 在这个阶段没有太多可操作的 DOM 相关的逻辑。如果你需要在 DOM 挂载之前对响应式数据进行一些最终的调整,可以使用。
onMounted(() => { … })
什么时候触发?
组件被挂载到页面上,真实的 DOM 已经渲染完成。 你可以访问和操作组件的真实 DOM 元素了(例如通过 uni.createSelectorQuery 查询元素信息)。组件中的子组件也可能已经挂载。
常用场景?
- DOM 操作: 获取组件的大小、位置,或对 Canvas、Video、Map 等需要实际渲染后才能操作的组件进行初始化或操作。例如,通过 uni.createSelectorQuery().select(‘#myElement’).boundingClientRect() 获取元素尺寸。
- 启动动画: 依赖真实 DOM 存在的动画效果,确保动画作用的元素已经就位。
- 第三方库初始化: 如果组件使用了需要挂载后才能初始化的第三方库(如一些图表库、地图SDK),应在此处进行初始化。
- 首次聚焦输入框: 确保输入框在页面渲染后自动获取焦点。
onBeforeUpdate(() => { … })
什么时候触发?
响应式数据发生变化,准备重新渲染 DOM 之前。 此时 DOM 尚未更新,你仍然可以访问到旧的 DOM 状态和更新前的响应式数据。
常用场景?
很少使用。 可以在这里获取更新前的数据状态,或者在 DOM 更新前进行一些清理操作。例如,如果你需要手动管理滚动位置,可以在这里保存当前位置,然后在 onUpdated 中恢复。
onUpdated(() => { … })
什么时候触发?
响应式数据变化导致组件内容重新渲染完成(真实的 DOM 已根据新数据更新)。
常用场景?
- DOM 更新后操作: 当组件数据更新,并且 DOM 视图已根据新数据重新渲染完毕后,进行一些依赖最新 DOM 状态的操作。例如,在列表数据更新后,调整滚动位置或重新计算某些元素的尺寸。
- 动画处理: 当某些数据显示出来后,启动与之相关的动画。
onBeforeUnmount(() => { … })
什么时候触发?
组件实例销毁之前。 组件仍然可用,事件监听器和子组件都还未被销毁。这是清除“副作用”前的最后机会。
常用场景?
onUnmounted(() => { … })
什么时候触发?
- 保存临时状态: 在组件被卸载前,保存一些用户输入、滚动位置、播放进度等临时数据(到 Vuex/Pinia 或本地存储)。
- 清除组件内部的监听器: 如果你在组件内部手动注册了一些 uni.onXxx 的监听,可以在这里提前取消,避免在 onUnmounted 中再处理,也避免在子组件销毁前就触发一些不必要的逻辑。
常用场景?
onErrorCaptured((err, instance, info) => { … })
什么时候触发?
当捕获到来自子组件或自身组件树中后代组件的错误时调用。 err 是错误对象,instance 是触发错误的组件实例,info 是错误源信息。
常用场景?
- 错误边界: 类似于 React 的 Error Boundary。捕获并处理子组件的错误,防止整个应用崩溃。可以显示一个错误提示界面,提供重试选项,或者向上级组件报告错误。
- 错误日志: 将捕获到的错误上报到错误监控平台。
- 本文仅作个人学习笔记使用,无商业用途。
- 如若转载,请先声明。