一墓陈、生命周期和運(yùn)行原理
寫微信小程序宪塔,他的生命周期不能不知道,不知道小程序就會(huì)出現(xiàn)各種bug而無法解決狐援。小助君公眾號(hào)帶你學(xué)習(xí)小程序的生命周期和運(yùn)行原理钢坦。
小程序由兩大線程組成:負(fù)責(zé)界面的線程(view thread)和服務(wù)線程(appservice thread),各司其職由互相配合
小程序的生命周期借鑒了Android的生命周期啥酱,如果你了解過Android的APP開發(fā)爹凹,那么理解小程序的就會(huì)很簡(jiǎn)單。
界面線程有四大狀態(tài):
1. 初始化狀態(tài):初始化界面線程所需要的工作镶殷,包括工作機(jī)制禾酱,基本和我們開發(fā)者沒有關(guān)系,等初始化完畢就向 “服務(wù)線程”發(fā)送初始化完畢信號(hào)绘趋,然后進(jìn)入等待傳回初始化數(shù)據(jù)狀態(tài)颤陶。
2.首次渲染狀態(tài):收到“服務(wù)線程”發(fā)來的初始化數(shù)據(jù)后(就是 json和js中的data數(shù)據(jù)),就開始渲染小程序界面陷遮,渲染完畢后滓走,發(fā)送“首次渲染完畢信號(hào)”給服務(wù)線程,并將頁(yè)面展示給用戶帽馋。
3.持續(xù)渲染狀態(tài):此時(shí)界面線程繼續(xù)一直等待“服務(wù)線程”通過this.setdata()函數(shù)發(fā)送來的界面數(shù)據(jù)搅方,只要收到就重新局部渲染,也因此只要更新數(shù)據(jù)并發(fā)送信號(hào)绽族,界面就自動(dòng)更新腰懂。
4.結(jié)束狀態(tài):你懂得。
服務(wù)線程五大狀態(tài):
1 初始化狀態(tài):無需和其他模塊交流项秉,跟小程序開發(fā)也沒多大關(guān)聯(lián),此階段就是啟動(dòng)服務(wù)線程所需的基本功能慷彤,比如信號(hào)發(fā)送模塊娄蔼。系統(tǒng)的初始化工作完畢,就調(diào)用自定義的onload和onshow底哗,
然后等待界面線程的“界面線程初始化完成”信號(hào)岁诉。
onload是只會(huì)首次渲染的時(shí)候執(zhí)行一次,onshow是每次界面切換都會(huì)執(zhí)行跋选,簡(jiǎn)單理解涕癣,這就是唯一差別。
2 等待激活狀態(tài):接收到“界面線程初始化完成”信號(hào)后前标,將初始化數(shù)據(jù)發(fā)送給“界面線程”坠韩,等待界面線程完成初次渲染距潘。
3.激活狀態(tài):收到界面線程發(fā)送來的“首次渲染完成”信號(hào)后,就進(jìn)入激活狀態(tài)既程序的正常運(yùn)行狀態(tài)只搁,并調(diào)用自定義的onReady()函數(shù)音比。
此狀態(tài)下就可以通過 this.setData 函數(shù)發(fā)送界面數(shù)據(jù)給界面線程進(jìn)行局部渲染,更新頁(yè)面氢惋。
4.后臺(tái)運(yùn)行狀態(tài):如果界面進(jìn)入后臺(tái)洞翩,服務(wù)線程就進(jìn)入后臺(tái)運(yùn)行狀態(tài),從目前的官方解讀來說焰望,這個(gè)狀態(tài)挺奇怪的骚亿,和激活狀態(tài)是相同的,也可以通過setdata函數(shù)更新界面的熊赖。
二来屠、路由跳轉(zhuǎn)
先說下getCurrentPages():
getCurrentPages()
函數(shù)用于獲取當(dāng)前頁(yè)面棧的實(shí)例,以數(shù)組形式按棧的順序給出秫舌,最后一個(gè)元素為當(dāng)前頁(yè)面的妖。
這是打印的getCurrentPages()
包括了整個(gè)page對(duì)象;
微信小程序關(guān)于路由跳轉(zhuǎn)的給出5個(gè)API文檔傳送門 足陨,結(jié)合文檔一下示意圖更加理解深刻:
1嫂粟、wx.navigateTo接口與頁(yè)面棧示意圖(不會(huì)將舊頁(yè)面出棧)
疑問:該圖為去年的,有五層限制墨缘。我自己試了一下getCurrentPages()最多會(huì)放10層星虹?
當(dāng)棧滿了(10層)之后,再調(diào)用wx.navigateTo()跳轉(zhuǎn)任何頁(yè)面镊讼,都不會(huì)成功宽涌。
特別注意的是,調(diào)用兩次wx.navigateTo('頁(yè)面B');wx.navigateTo('頁(yè)面B');蝶棋,那么棧里存在兩個(gè)頁(yè)面B(或者說兩個(gè)頁(yè)面B的實(shí)例)卸亮,如下圖。
2玩裙、wx.redirectTo接口與頁(yè)面棧示意圖(會(huì)將舊頁(yè)面出棧兼贸,再將需要跳轉(zhuǎn)到的頁(yè)面入棧)
3、wx.navigateBack
這就是棧里的頁(yè)面一個(gè)一個(gè)出棧吃溅。當(dāng)最后一個(gè)頁(yè)面(首頁(yè)A)出棧后溶诞,也就退出了小程序。給wx.navigateBack添加了一個(gè)參數(shù)delta决侈,用于決定需要返回幾層頁(yè)面螺垢;如果delta大于等于現(xiàn)有頁(yè)面數(shù)(也就是棧里的頁(yè)面數(shù)),則返回到首頁(yè)。
4枉圃、wx.switchTab(跳轉(zhuǎn)到 tabBar 頁(yè)面功茴,并關(guān)閉其他所有非 tabBar 頁(yè)面);
5、****wx.reLaunch(關(guān)閉所有頁(yè)面讯蒲,打開到應(yīng)用內(nèi)的某個(gè)頁(yè)面痊土。)
這個(gè)就是將所有頁(yè)面棧中的頁(yè)面清空,添加當(dāng)前頁(yè)面墨林;
應(yīng)用
1赁酝,比如我們?cè)谧鲰?xiàng)目的時(shí)候自定義了返回按鈕,其實(shí)我們直接操作getCurrentPages()
中返回的數(shù)組配合wx.navigateBack決定跳到哪個(gè)頁(yè)面旭等;
2酌呆,刷新當(dāng)前頁(yè):
(1)小程序不會(huì)像js中那樣有l(wèi)ocation.reload()這種dom操作;
(2)如果用this.onLoad();this.onShow();刷新搔耕,data中的數(shù)據(jù)不會(huì)得到有效的更新隙袁;還需要重新setdata一次;操作麻煩弃榨;
(3)我們還是直接操作getCurrentPages()菩收;取最后一個(gè)元素及為當(dāng)前元素,拿到route,和options鲸睛。刷新動(dòng)作就是去掉最后一個(gè)元素再重新根據(jù)拿到的數(shù)據(jù)跳轉(zhuǎn)當(dāng)前頁(yè)娜饵;