onLaunch / onShow / onHide 三個(ge)回調(diao)是App實(shi)例(li)的(de)生命周期函數
“小程(cheng)序(xu)(xu)(xu)”指(zhi)的(de)(de)(de)是產品層面(mian)(mian)的(de)(de)(de)程(cheng)序(xu)(xu)(xu),而“程(cheng)序(xu)(xu)(xu)”指(zhi)的(de)(de)(de)是代(dai)(dai)碼(ma)層面(mian)(mian)的(de)(de)(de)程(cheng)序(xu)(xu)(xu)實例(li),為(wei)了(le)避免(mian)誤解,下文采(cai)用App來代(dai)(dai)替代(dai)(dai)碼(ma)層面(mian)(mian)的(de)(de)(de)“程(cheng)序(xu)(xu)(xu)”概念。
宿主環境提供了 App() 構造(zao)器用來注冊一(yi)個程(cheng)序(xu)App,需要留意的是(shi)App() 構造(zao)器必須寫在(zai)項目根目錄的app.js里,App實例(li)(li)是(shi)單例(li)(li)對象,在(zai)其他JS腳本中可以(yi)使用宿主環境提供的 getApp() 來獲(huo)取(qu)程(cheng)序(xu)實例(li)(li)。
代(dai)碼獲取App實例
// other.js var appInstance = getApp()
App() 的(de)調(diao)用方式如代(dai)碼清(qing)單(dan)3-4所示(shi),App構(gou)造器接(jie)受一個Object參(can)數(shu),參(can)數(shu)說(shuo)明如表3-1所示(shi),其(qi)中(zhong)onLaunch / onShow / onHide 三個回調(diao)是App實(shi)例的(de)生(sheng)命周期函數(shu),我們(men)(men)會(hui)在(zai)(zai)后文(wen)展開(kai);onError我們(men)(men)暫(zan)時不在(zai)(zai)本章展開(kai),我們(men)(men)會(hui)在(zai)(zai)第8章里詳(xiang)細討論;App的(de)其(qi)他參(can)數(shu)我們(men)(men)也放(fang)在(zai)(zai)后文(wen)進行展開(kai)。
代碼(ma) 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實例的生命周期函數。
在(zai)微信客(ke)戶端中打(da)(da)開(kai)小程(cheng)序有很(hen)多途徑:從(cong)群聊(liao)會話里打(da)(da)開(kai),從(cong)小程(cheng)序列表(biao)中打(da)(da)開(kai),通過微信掃(sao)(sao)一掃(sao)(sao)二維碼(ma)打(da)(da)開(kai),從(cong)另外一個小程(cheng)序打(da)(da)開(kai)當前小程(cheng)序等,針對不(bu)同(tong)途徑的打(da)(da)開(kai)方式,小程(cheng)序有時需要(yao)(yao)做不(bu)同(tong)的業(ye)務處理,所以微信客(ke)戶端會把打(da)(da)開(kai)方式帶給onLaunch和onShow的調(diao)用參數options,示(shi)例代(dai)碼(ma)以及詳細參數如代(dai)碼(ma)清單3-5和表(biao)3-2所示(shi)。需要(yao)(yao)留意小程(cheng)序的宿主環境(jing)在(zai)迭代(dai)更新(xin)過程(cheng)會增加不(bu)少(shao)打(da)(da)開(kai)場(chang)景,因此要(yao)(yao)獲取最(zui)新(xin)的場(chang)景值說明請查看官(guan)方文檔:。
代碼(ma)清單3-5 onLaunch和onShow帶參數
App({
onLaunch: function(options) { console.log(options) },
onShow: function(options) { console.log(options) }
})
|
onLaunch,onShow參數(shu)
| 字段 | 類型 | 描述 |
|---|---|---|
| path | String | 打開小程序的頁面路徑 |
| query | Object | 打開小程序的頁面參數query |
| scene | Number | 打開小程序的場景值,詳細場景值請參考小程序官方文檔 |
| shareTicket | String | shareTicket,詳見小程序官方文檔 |
| referrerInfo | Object | 當場景為由從另一個小程序或公眾號或App打開時,返回此字段 |
| referrerInfo.appId | String | 來源小程序或公眾號或App的 appId,詳見下方說明 |
| referrerInfo.extraData | Object | 來源小程序傳過來的數據,scene=1037或1038時支持 |
以下(xia)場景支持(chi)返回 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
|
與此(ci)同時(shi),我們要(yao)特別留意一點,所有(you)(you)頁面(mian)的(de)腳本邏輯都跑在(zai)同一個JsCore線程(cheng),頁面(mian)使用setTimeout或(huo)者(zhe)setInterval的(de)定時(shi)器(qi)(qi),然后(hou)跳(tiao)轉(zhuan)到其(qi)他(ta)頁面(mian)時(shi),這些定時(shi)器(qi)(qi)并沒有(you)(you)被(bei)清除,需要(yao)開發者(zhe)自己(ji)在(zai)頁面(mian)離開的(de)時(shi)候(hou)進行清理。
小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu)啟動(dong)會有兩種(zhong)情(qing)況,一種(zhong)是(shi)「冷啟動(dong)」,一種(zhong)是(shi)「熱(re)啟動(dong)」。 假如用(yong)戶已經(jing)打(da)開(kai)過某小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu),然后在一定(ding)時(shi)(shi)間內(nei)再(zai)次(ci)打(da)開(kai)該(gai)小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu),此(ci)時(shi)(shi)無需重新啟動(dong),只需將(jiang)后臺(tai)態(tai)的小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu)切換到前臺(tai),這(zhe)個過程(cheng)(cheng)就是(shi)熱(re)啟動(dong);冷啟動(dong)指的是(shi)用(yong)戶首次(ci)打(da)開(kai)或小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu)被微信主動(dong)銷毀后再(zai)次(ci)打(da)開(kai)的情(qing)況,此(ci)時(shi)(shi)小(xiao)(xiao)(xiao)(xiao)程(cheng)(cheng)序(xu)(xu)需要重新加載啟動(dong)。
更新(xin)(xin)機制:小(xiao)程(cheng)序冷啟動時(shi)如果(guo)發現有新(xin)(xin)版(ban)本,將會異步下載新(xin)(xin)版(ban)本的(de)代碼包,并同時(shi)用(yong)客(ke)戶(hu)端(duan)本地的(de)包進行啟動,即新(xin)(xin)版(ban)本的(de)小(xiao)程(cheng)序需要等下一次冷啟動才(cai)會應用(yong)上。