onLaunch / onShow / onHide 三个回调是App实例的生命周期函数
“小程序”指的是产品层面的程序,而“程序”指的是代码层面的程序实例,为了避免误解,下文采用App来代替代码层面的“程序”概念。
宿主环境提供了 App() 构造器用来注册一个程序App,需要留意的是App() 构造器必须写在项目根目录的app.js里,App实例是单例对象,在其他JS脚本中可以使用宿主环境提供的 getApp() 来获取程序实例。
代码获取App实例
// other.js var appInstance = getApp()
App() 的调用方式如代码清单3-4所示,App构造器接受一个Object参数,参数说明如表3-1所示,其中onLaunch / onShow / onHide 三个回调是App实例的生命周期函数,我们会在后文展开;onError我们暂时不在本章展开,我们会在第8章里详细讨论;App的其他参数我们也放在后文进行展开。
代码 App构造器
App({ onLaunch: function(options) {}, onShow: function(options) {}, onHide: function() {}, onError: function(msg) {}, globalData: 'I am global data' }) |
App构造器参数
参数属性 | 类型 | 描述 |
---|---|---|
onLaunch | Function | 当小程序初始化完成时,会触发 onLaunch(全局只触发一次) |
onShow | Function | 当小程序启动,或从后台进入前台显示,会触发 onShow |
onHide | Function | 当小程序从前台进入后台,会触发 onHide |
onError | Function | 当小程序发生脚本错误,或者 API 调用失败时,会触发 onError 并带上错误信息 |
其他字段 | 任意 | 可以添加任意的函数或数据到 Object 参数中,在App实例回调用 this 可以访问 |
初次进入小程序的时候,微信客户端初始化好宿主环境,同时从网络下载或者从本地缓存中拿到小程序的代码包,把它注入到宿主环境,初始化完毕后,微信客户端就会给App实例派发onLaunch事件,App构造器参数所定义的onLaunch方法会被调用。
进入小程序之后,用户可以点击右上角的关闭,或者按手机设备的Home键离开小程序,此时小程序并没有被直接销毁,我们把这种情况称为“小程序进入后台状态”,App构造器参数所定义的onHide方法会被调用。
当再次回到微信或者再次打开小程序时,微信客户端会把“后台”的小程序唤醒,我们把这种情况称为“小程序进入前台状态”,App构造器参数所定义的onShow方法会被调用。
我们可以看到,App的生命周期是由微信客户端根据用户操作主动触发的。为了避免程序上的混乱,我们不应该从其他代码里主动调用App实例的生命周期函数。
在微信客户端中打开小程序有很多途径:从群聊会话里打开,从小程序列表中打开,通过微信扫一扫二维码打开,从另外一个小程序打开当前小程序等,针对不同途径的打开方式,小程序有时需要做不同的业务处理,所以微信客户端会把打开方式带给onLaunch和onShow的调用参数options,示例代码以及详细参数如代码清单3-5和表3-2所示。需要留意小程序的宿主环境在迭代更新过程会增加不少打开场景,因此要获取最新的场景值说明请查看官方文档:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/app-service/app.html。
代码清单3-5 onLaunch和onShow带参数
App({ onLaunch: function(options) { console.log(options) }, onShow: function(options) { console.log(options) } }) |
onLaunch,onShow参数
字段 | 类型 | 描述 |
---|---|---|
path | String | 打开小程序的页面路径 |
query | Object | 打开小程序的页面参数query |
scene | Number | 打开小程序的场景值,详细场景值请参考小程序官方文档 |
shareTicket | String | shareTicket,详见小程序官方文档 |
referrerInfo | Object | 当场景为由从另一个小程序或公众号或App打开时,返回此字段 |
referrerInfo.appId | String | 来源小程序或公众号或App的 appId,详见下方说明 |
referrerInfo.extraData | Object | 来源小程序传过来的数据,scene=1037或1038时支持 |
以下场景支持返回 referrerInfo.appId
场景值 | 场景 | appId信息含义 |
---|---|---|
1020 | 公众号 profile | 页相关小程序列表 返回来源公众号 appId |
1035 | 公众号自定义菜单 | 返回来源公众号 appId |
1036 | App 分享消息卡片 | 返回来源应用 appId |
1037 | 小程序打开小程序 | 返回来源小程序 appId |
1038 | 从另一个小程序返回 | 返回来源小程序 appId |
1043 | 公众号模板消息 | 返回来源公众号 appId |
之前说到小程序的JS脚本是运行在JsCore的线程里,小程序的每个页面各自有一个WebView线程进行渲染,所以小程序切换页面时,小程序逻辑层的JS脚本运行上下文依旧在同一个JsCore线程中。
在上文中说道App实例是单例的,因此不同页面直接可以通过App实例下的属性来共享数据。App构造器可以传递其他参数作为全局属性以达到全局共享数据的目的。
代码小程序全局共享数据
// app.js App({ globalData: 'I am global data' // 全局共享数据 }) // 其他页面脚本other.js var appInstance = getApp() console.log(appInstance.globalData) // 输出: I am global data |
与此同时,我们要特别留意一点,所有页面的脚本逻辑都跑在同一个JsCore线程,页面使用setTimeout或者setInterval的定时器,然后跳转到其他页面时,这些定时器并没有被清除,需要开发者自己在页面离开的时候进行清理。
小程序启动会有两种情况,一种是「冷启动」,一种是「热启动」。 假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。
更新机制:小程序冷启动时如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。