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的定時器,然后跳轉到其他頁面時,這些定時器并沒有被清除,需要開發者自己在頁面離開的時候進行清理。
小程序啟動會有兩種情況,一種是「冷啟動」,一種是「熱啟動」。 假如用戶已經打開過某小程序,然后在一定時間內再次打開該小程序,此時無需重新啟動,只需將后臺態的小程序切換到前臺,這個過程就是熱啟動;冷啟動指的是用戶首次打開或小程序被微信主動銷毀后再次打開的情況,此時小程序需要重新加載啟動。
更新機制:小程序冷啟動時如果發現有新版本,將會異步下載新版本的代碼包,并同時用客戶端本地的包進行啟動,即新版本的小程序需要等下一次冷啟動才會應用上。