小程序生命周期解析:App Lifecycle与Page Lifecycle的协同运作

7 阅读5分钟

小程序生命周期解析:App Lifecycle与Page Lifecycle的协同运作

小程序的生命周期是开发者构建稳定、高效应用的核心知识体系,其分为应用生命周期(App Lifecycle)页面生命周期(Page Lifecycle) 两个层级。两者通过嵌套式触发机制,共同管理小程序从启动到销毁的全流程状态变化。本文将结合具体场景与代码示例,深入解析两者的差异与协作逻辑。

一、应用生命周期(App Lifecycle):全局状态管理中枢

应用生命周期由App()构造器定义,负责管理小程序实例的全局状态,其核心函数包括:

1. onLaunch:初始化启动

  • 触发时机:小程序首次启动时触发(仅一次),包括冷启动和热启动(如从后台恢复)。

  • 典型场景

    • 获取用户授权信息(如uni.login()获取code)
    • 初始化全局配置(如主题、缓存策略)
    • 检查版本更新并提示用户
  • 代码示例

    javascript
    1App({
    2  onLaunch(options) {
    3    console.log('小程序启动,场景值:', options.scene);
    4    // 静默登录
    5    uni.login({
    6      success: (res) => {
    7        if (res.code) {
    8          // 发送code到服务器换取openid
    9        }
    10      }
    11    });
    12    // 检查更新
    13    if (wx.canIUse('getUpdateManager')) {
    14      const updateManager = wx.getUpdateManager();
    15      updateManager.onCheckForUpdate((res) => {
    16        if (res.hasUpdate) {
    17          updateManager.onUpdateReady(() => {
    18            wx.showModal({
    19              title: '更新提示',
    20              content: '新版本已准备好,是否重启应用?',
    21              success: (res) => {
    22                if (res.confirm) updateManager.applyUpdate();
    23              }
    24            });
    25          });
    26        }
    27      });
    28    }
    29  }
    30});
    31
    

2. onShow:前台激活

  • 触发时机

    • 小程序启动后进入前台
    • 从后台切回前台(如用户返回微信聊天界面后重新打开小程序)
  • 典型场景

    • 刷新用户活跃数据
    • 检查网络状态并重连
    • 恢复音乐/视频播放
  • 代码示例

    javascript
    1App({
    2  onShow(options) {
    3    console.log('小程序进入前台,场景值:', options.scene);
    4    // 统计用户活跃
    5    uni.request({
    6      url: 'https://api.example.com/stats/active',
    7      method: 'POST',
    8      data: { timestamp: Date.now() }
    9    });
    10    // 检查网络状态
    11    uni.getNetworkType({
    12      success: (res) => {
    13        if (res.networkType === 'none') {
    14          uni.showToast({ title: '网络已断开', icon: 'none' });
    15        }
    16      }
    17    });
    18  }
    19});
    20
    

3. onHide:后台休眠

  • 触发时机:小程序从前台切至后台(如用户按Home键或切换至其他应用)

  • 典型场景

    • 保存临时数据(如表单草稿)
    • 清除定时器
    • 暂停媒体播放
  • 代码示例

    javascript
    1App({
    2  onHide() {
    3    console.log('小程序进入后台');
    4    // 保存购物车状态
    5    const cart = uni.getStorageSync('cart') || [];
    6    uni.setStorageSync('cart_backup', cart);
    7    // 清除全局定时器
    8    if (this.globalTimer) clearInterval(this.globalTimer);
    9  }
    10});
    11
    

4. onError:错误捕获

  • 触发时机:发生脚本错误或API调用失败时

  • 典型场景

    • 上报错误日志到服务器
    • 提示用户重试
  • 代码示例

    javascript
    1App({
    2  onError(err) {
    3    console.error('小程序错误:', err);
    4    uni.request({
    5      url: 'https://api.example.com/error/report',
    6      method: 'POST',
    7      data: {
    8        error: err.message,
    9        stack: err.stack,
    10        timestamp: Date.now()
    11      }
    12    });
    13    uni.showToast({ title: '服务异常,请稍后重试', icon: 'none' });
    14  }
    15});
    16
    

二、页面生命周期(Page Lifecycle):单页状态管理单元

页面生命周期由Page()构造器定义,负责管理单个页面的加载、渲染、交互和销毁过程,其核心函数包括:

1. onLoad:页面加载

  • 触发时机:页面初次加载时触发(仅一次)

  • 典型场景

    • 获取路由参数(如options.id
    • 初始化页面数据
    • 发起一次性数据请求
  • 代码示例

    javascript
    1Page({
    2  onLoad(options) {
    3    console.log('页面加载,参数:', options);
    4    // 根据ID加载商品详情
    5    if (options.id) {
    6      this.loadProductDetail(options.id);
    7    }
    8    // 初始化表单数据
    9    this.setData({ form: { name: '', phone: '' } });
    10  },
    11  loadProductDetail(id) {
    12    uni.request({
    13      url: `https://api.example.com/products/${id}`,
    14      success: (res) => {
    15        this.setData({ product: res.data });
    16      }
    17    });
    18  }
    19});
    20
    

2. onShow:页面显示

  • 触发时机

    • 页面初次加载完成后
    • 从其他页面返回时
    • 从后台切回前台时
  • 典型场景

    • 刷新动态数据(如用户收藏状态)
    • 恢复页面动画
    • 统计页面访问
  • 代码示例

    javascript
    1Page({
    2  onShow() {
    3    console.log('页面显示');
    4    // 刷新收藏状态
    5    this.checkFavoriteStatus();
    6    // 恢复动画
    7    if (this.animation) this.animation.play();
    8  },
    9  checkFavoriteStatus() {
    10    const userId = uni.getStorageSync('userId');
    11    uni.request({
    12      url: `https://api.example.com/favorites/check?userId=${userId}&productId=${this.data.product.id}`,
    13      success: (res) => {
    14        this.setData({ isFavorite: res.data.isFavorite });
    15      }
    16    });
    17  }
    18});
    19
    

3. onReady:页面渲染完成

  • 触发时机:页面初次渲染完成时触发(仅一次)

  • 典型场景

    • 操作DOM节点(如获取Canvas上下文)
    • 启动依赖布局的动画
  • 代码示例

    javascript
    1Page({
    2  onReady() {
    3    console.log('页面渲染完成');
    4    // 获取Canvas上下文
    5    const query = uni.createSelectorQuery().in(this);
    6    query.select('#myCanvas')
    7      .fields({ node: true, size: true })
    8      .exec((res) => {
    9        const canvas = res[0].node;
    10        const ctx = canvas.getContext('2d');
    11        // 绘制动画
    12        this.animateCanvas(ctx);
    13      });
    14  },
    15  animateCanvas(ctx) {
    16    // 动画逻辑...
    17  }
    18});
    19
    

4. onHide:页面隐藏

  • 触发时机

    • 跳转至其他页面时
    • 切至后台时
  • 典型场景

    • 保存页面状态(如表单输入)
    • 暂停页面定时器
  • 代码示例

    javascript
    1Page({
    2  data: { form: { name: '', phone: '' } },
    3  onHide() {
    4    console.log('页面隐藏');
    5    // 保存表单草稿
    6    uni.setStorageSync('form_draft', this.data.form);
    7    // 暂停定时器
    8    if (this.timer) clearInterval(this.timer);
    9  }
    10});
    11
    

5. onUnload:页面销毁

  • 触发时机:页面被完全卸载时触发(如调用uni.redirectTouni.reLaunch

  • 典型场景

    • 清理页面资源(如WebSocket连接)
    • 取消事件监听
  • 代码示例

    javascript
    1Page({
    2  onUnload() {
    3    console.log('页面销毁');
    4    // 清理WebSocket连接
    5    if (this.socket) {
    6      this.socket.close();
    7      this.socket = null;
    8    }
    9    // 移除全局事件监听
    10    uni.offCustomEvent(this.handleCustomEvent);
    11  }
    12});
    13
    

三、生命周期协同机制:嵌套触发与状态传递

小程序生命周期的核心在于应用级与页面级的嵌套触发,其典型流程如下:

  1. 首次启动

    1App.onLaunch → App.onShow → Page.onLoad → Page.onShow → Page.onReady
    2
    
  2. 页面跳转(A→B)

    1PageA.onHide → PageB.onLoad → PageB.onShow → PageB.onReady
    2
    
  3. 返回上一页(B→A)

    1PageB.onUnload → PageA.onShow
    2
    
  4. 切至后台

    1Page.onHide → App.onHide
    2
    
  5. 切回前台

    1App.onShow → Page.onShow
    2
    

四、最佳实践:生命周期的合理利用

  1. 数据初始化

    • 全局数据:在App.onLaunch中加载
    • 页面数据:在Page.onLoad中加载
  2. 性能优化

    • 避免在onShow中发起耗时请求(可结合防抖机制)
    • onHide/onUnload中及时清理资源
  3. 状态同步

    • 利用App.globalData共享全局状态
    • 通过路由参数传递页面间数据
  4. 错误处理

    • App.onError中统一捕获未处理异常
    • 在页面中捕获具体业务错误

结语

小程序的生命周期体系通过应用级与页面级的分层设计,实现了全局状态与局部状态的解耦管理。开发者需深入理解各生命周期函数的触发时机与典型场景,结合具体业务需求合理编排代码逻辑,才能构建出高效、稳定的小程序应用。