摘要:運(yùn)行機(jī)制小程序啟動會有兩種情況,一種是冷啟動,一種是熱啟動。建議小程序在必要時(shí)使用監(jiān)聽內(nèi)存告警事件,進(jìn)行必要的內(nèi)存清理。
前言
以小程序?yàn)榍腥朦c(diǎn),深入理解總結(jié)方方面面的知識點(diǎn),做成系列文章,希望能得到大神的指點(diǎn)和幫助新人入門,承上啟下才是好程序猿
由于是系列第一篇文章,緊跟著的是一大段廢話,只關(guān)心技術(shù)的可以跳過
轉(zhuǎn)眼半年又要過去了,意味著來新公司快半年了,離上次寫文章也半年了,渾渾噩噩得當(dāng)碼農(nóng)半年了,這半年主要是搬磚(定制VUE和小程序)各種重復(fù)做功,說實(shí)話沒太大長進(jìn),核心功能公司模板有了,大bug改不動,小bug改不完,大差不差交工就行,當(dāng)然這是我自己的選擇,自己XXX含著淚也要XX,自行腦補(bǔ)
大家應(yīng)該都知道有一種公司叫做外包公司,利弊網(wǎng)上一大堆,關(guān)鍵看你怎么選擇了
我現(xiàn)在就在外包公司,當(dāng)初的打算就是用工作量來提高熟練度,也確實(shí)達(dá)成了“目標(biāo)”,半年前,對于vue和小程序,也就是mvvm,只是理論層面,實(shí)際做項(xiàng)目還是有點(diǎn)怵,現(xiàn)在嘛結(jié)合上面的吐槽,前面的目標(biāo)只能說達(dá)成了50%,畢竟做定制不管黑貓白貓,抓到老鼠就是好貓,遇到問題也是見招拆招,性能?迭代?可復(fù)用性?冗余?這些和我有關(guān)系嗎?
針對上面這種情況,也就出現(xiàn)了很多人生導(dǎo)師的吶喊——待在外包不能超過半年,不然你就廢了?。。。脕肀薏咦约海?/p>
現(xiàn)在我們公司已經(jīng)準(zhǔn)備向產(chǎn)品轉(zhuǎn)型了,我也從定制部門轉(zhuǎn)到了小程序產(chǎn)品部門,正好深入理解一波,和公司共同成長
感覺知識也是金字塔狀的,剛開始我們在頂端,越往下拓展的就越多,我發(fā)現(xiàn)每當(dāng)我想深入理解一個(gè)方面,必然引出更多關(guān)聯(lián)知識,那怎么辦呢,好記性不如爛筆頭,在這年末年初之際,先給2019年開個(gè)好頭
小程序App生命周期小程序App生命周期是在app.js里面調(diào)用的,App(Object)函數(shù)用來注冊一個(gè)小程序,接受一個(gè) Object 參數(shù),指定其小程序的生命周期回調(diào)
App() 必須在 app.js 中調(diào)用,必須調(diào)用且只能調(diào)用一次,不然會出現(xiàn)無法預(yù)期的后果
以上應(yīng)該一眼就能看明白,以下主要講講前臺、后臺定義和運(yùn)行機(jī)制等
1 . 前臺、后臺定義
當(dāng)用戶點(diǎn)擊左上角關(guān)閉,或者按了設(shè)備 Home 鍵離開微信,小程序并沒有直接銷毀,而是進(jìn)入了后臺onHide;當(dāng)再次進(jìn)入微信或再次打開小程序,又會從后臺進(jìn)入前臺onShow。需要注意的是:只有當(dāng)小程序進(jìn)入后臺一定時(shí)間,或者系統(tǒng)資源占用過高,才會被真正的銷毀。
2 . 運(yùn)行機(jī)制
小程序啟動會有兩種情況,一種是「冷啟動」,一種是「熱啟動」。 假如用戶已經(jīng)打開過某小程序,然后在一定時(shí)間內(nèi)再次打開該小程序,此時(shí)無需重新啟動,只需將后臺態(tài)的小程序切換到前臺onShow,這個(gè)過程就是熱啟動;冷啟動指的是用戶首次打開或小程序被微信主動銷毀后再次打開的情況,此時(shí)小程序需要重新加載啟動onLauch
小程序沒有重啟的概念
當(dāng)小程序進(jìn)入后臺,客戶端會維持一段時(shí)間的運(yùn)行狀態(tài),超過一定時(shí)間后(目前是5分鐘)會被微信主動銷毀
在 iOS 上,當(dāng)微信客戶端在一定時(shí)間間隔內(nèi)(目前是 5 秒)連續(xù)收到兩次及以上系統(tǒng)內(nèi)存告警時(shí),會主動進(jìn)行小程序的銷毀,并提示用戶 「該小程序可能導(dǎo)致微信響應(yīng)變慢被終止」。建議小程序在必要時(shí)使用 wx.onMemoryWarning 監(jiān)聽內(nèi)存告警事件,進(jìn)行必要的內(nèi)存清理。
3 . 更新機(jī)制
小程序冷啟動時(shí)如果發(fā)現(xiàn)有新版本,將會異步下載新版本的代碼包,并同時(shí)用客戶端本地的包進(jìn)行啟動,即新版本的小程序需要等下一次冷啟動才會應(yīng)用上。 如果需要馬上應(yīng)用最新版本,可以使用 wx.getUpdateManager API 進(jìn)行處理
小程序強(qiáng)制更新
//注意,小程序的更新的api需要基礎(chǔ)庫在1.9.90以上 const updateManager = wx.getUpdateManager() updateManager.onCheckForUpdate(function (res) { // 請求完新版本信息的回調(diào),省略回調(diào)會報(bào)錯(cuò),如下圖 console.log(res.hasUpdate) }) updateManager.onUpdateReady(function () { wx.showModal({ title: "更新提示", content: "新版本已經(jīng)準(zhǔn)備好,是否重啟應(yīng)用?", success: function (res) { if (res.confirm) { // 新的版本已經(jīng)下載好,調(diào)用 applyUpdate 應(yīng)用新版本并重啟 updateManager.applyUpdate() } } }) }) updateManager.onUpdateFailed(function () { // 新的版本下載失敗 wx.showModal({ title: "更新提示", content: "新版本下載失敗", showCancel:false }) })
3 . 再次打開邏輯
用戶打開小程序的預(yù)期有以下兩類場景:1、打開首頁 2、打開指定頁面
現(xiàn)在要打開的是首頁,如果上一次退出的時(shí)候是首頁,則保留狀態(tài);否則,清空原來的頁面棧,打開首頁(相當(dāng)于執(zhí)行 wx.reLaunch 到首頁)
現(xiàn)在要打開的是指定頁面,不管上次在什么頁面,清空原來的頁面棧,打開指定頁面(相當(dāng)于執(zhí)行 wx.reLaunch 到指定頁)
小程序Page生命周期Page(Object) 函數(shù)用來注冊一個(gè)頁面。接受一個(gè) Object 類型參數(shù),其指定頁面的初始數(shù)據(jù)、生命周期回調(diào)、事件處理函數(shù)等
引用一張不錯(cuò)的圖片來讓你一目了然,圖片來源于網(wǎng)絡(luò)補(bǔ)充:app.onPageNotFound(Object)
基礎(chǔ)庫 1.9.90 開始支持,低版本需做兼容處理。
小程序要打開的頁面不存在時(shí)觸發(fā),也可以使用 wx.onPageNotFound 綁定監(jiān)聽
開發(fā)者可以在回調(diào)中進(jìn)行頁面重定向,但必須在回調(diào)中同步處理,異步處理(例如 setTimeout 異步執(zhí)行)無效
主要用于輪播、魔方等動態(tài)指定跳轉(zhuǎn)頁面的場景,避免出現(xiàn)頁面不存在的情況
App({ onPageNotFound(res) { // 可以封裝一個(gè)小程序跳轉(zhuǎn)函數(shù),智能解決tabbar頁面跳轉(zhuǎn)的問題 wx.redirectTo({ url: "pages/..." }) } })生命周期執(zhí)行順序
生命周期執(zhí)行順序
分別了解了App和Page的生命周期函數(shù),那他們之間有何關(guān)聯(lián)
吐槽一句,好多文章說什么app的生命周期函數(shù)onLauch可能會在page的onLoad之后觸發(fā),搞得我一臉懵逼,說話這么不嚴(yán)謹(jǐn),真的好嗎???
先看看正常的生命周期App({ onLaunch() { console.log("app---onLaunch"); }, onShow() { console.log("app---onShow"); }, onHide() { console.log("app---onHide"); } }) Page({ onLoad(options) { console.log("page---onLoad"); }, onReady() { console.log("page---onReady"); }, onShow() { console.log("page---onShow"); }, onHide() { console.log("page---onHide"); }, onUnload() { console.log("page---onUnload"); } })控制臺輸出 應(yīng)該說永遠(yuǎn)是這個(gè)順序,現(xiàn)在再加點(diǎn)代碼,就用官方的例子
App({ onLaunch() { console.log("app---onLaunch"); // 獲取用戶信息 wx.getSetting({ success: res => { if (res.authSetting["scope.userInfo"]) { // 已經(jīng)授權(quán),可以直接調(diào)用 getUserInfo 獲取頭像昵稱,不會彈框 wx.getUserInfo({ success: res => { // 可以將 res 發(fā)送給后臺解碼出 unionId this.globalData.userInfo = res.userInfo console.log("app---onLaunch---success"); // 由于 getUserInfo 是網(wǎng)絡(luò)請求,可能會在 Page.onLoad 之后才返回 // 所以此處加入 callback 以防止這種情況 if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } } }) } }) Page({ onLoad(options) { console.log("page---onLoad"); if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } else if (this.data.canIUse) { // 由于 getUserInfo 是網(wǎng)絡(luò)請求,可能會在 Page.onLoad 之后才返回 // 所以此處加入 callback 以防止這種情況 app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { // 在沒有 open-type=getUserInfo 版本的兼容處理 wx.getUserInfo({ success: res => { app.globalData.userInfo = res.userInfo this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) } } })控制臺輸出
可以看出小程序生命周期函數(shù)并沒有錯(cuò)亂,只是加了異步操作
你永遠(yuǎn)不知道異步操作會排在正常周期的哪一個(gè)位置
解決方案
例子中已經(jīng)給出了callback的方案,現(xiàn)在也可以使用promise來解決
1 . callback
解釋一波:Page頁面判斷當(dāng)前app.globalData.userInfo是否有值
如果有,說明異步操作很順利,當(dāng)做同步往下操作即可
如果沒有,則定義一個(gè)app方法(回調(diào)函數(shù))app.userInfoReadyCallback = res => {...}
因?yàn)镻age.onLoad沒有順利拿到app.globalData.userInfo,說明App頁面請求success異步操作滯后了
此時(shí)APP頁面不僅會給globalData.userInfo賦值,還會執(zhí)行Page頁面定義的回調(diào)方法,完成業(yè)務(wù)邏輯
以上例子是官方對于授權(quán)之后的操作流程示例,實(shí)際使用替換自己的初始化函數(shù)和業(yè)務(wù)邏輯
注意事項(xiàng)
app.onLaunch全局只觸發(fā)一次,也就是打開的第一個(gè)頁面會有異步問題,打開第二個(gè)頁面肯定是可以拿到初始化數(shù)據(jù)的,但是小程序可以從不同場景進(jìn)入,可能打開的并非是首頁,這時(shí)就需要給每一個(gè)可能被第一次就打開的頁面,寫回調(diào)函數(shù),暫時(shí)沒想到類似vue那種設(shè)置全局路由回調(diào)的方案
2 . promise
最終效果應(yīng)該和回調(diào)一樣,之前小程序不支持promise,一直沒有好好用過,等以后多帶帶研究~
Page實(shí)例生命周期先來看一張很熟悉的圖咋一看,什么鬼,好吧~我聽你的,以后再說~
官方原話(以下內(nèi)容你不需要立馬完全弄明白,不過以后它會有幫助)
轉(zhuǎn)眼間,以后就到啦!好在有大佬解釋過了,借花獻(xiàn)佛,誰讓我是搬運(yùn)工呢(最后會貼上參考文章鏈接)
Page實(shí)例由兩大線程組成負(fù)責(zé)界面的線程(view thread)和服務(wù)線程(appservice thread),各司其職又互相配合
界面線程有四大狀態(tài):
初始化狀態(tài):初始化界面線程所需要的工作,包括工作機(jī)制,基本和我們開發(fā)者沒有關(guān)系,等初始化完畢就向 “服務(wù)線程”發(fā)送初始化完畢信號,然后進(jìn)入等待傳回初始化數(shù)據(jù)狀態(tài)
首次渲染狀態(tài):收到“服務(wù)線程”發(fā)來的初始化數(shù)據(jù)后(就是 json和js中的data數(shù)據(jù)),就開始渲染小程序界面,渲染完畢后,發(fā)送“首次渲染完畢信號”給服務(wù)線程,并將頁面展示給用戶
持續(xù)渲染狀態(tài):此時(shí)界面線程繼續(xù)一直等待“服務(wù)線程”通過this.setdata()函數(shù)發(fā)送來的界面數(shù)據(jù),只要收到就重新局部渲染,也因此只要更新數(shù)據(jù)并發(fā)送信號,界面就自動更新
結(jié)束狀態(tài):你懂得
服務(wù)線程五大狀態(tài):
初始化狀態(tài):無需和其他模塊交流,跟小程序開發(fā)也沒多大關(guān)聯(lián),此階段就是啟動服務(wù)線程所需的基本功能,比如信號發(fā)送模塊。系統(tǒng)的初始化工作完畢,就調(diào)用自定義的onload和onshow,
然后等待界面線程的“界面線程初始化完成”信號。
onload是只會首次渲染的時(shí)候執(zhí)行一次,onshow是每次界面切換都會執(zhí)行,簡單理解,這就是唯一差別
等待激活狀態(tài):接收到“界面線程初始化完成”信號后,將初始化數(shù)據(jù)發(fā)送給“界面線程”,等待界面線程完成初次渲染
激活狀態(tài):收到界面線程發(fā)送來的“首次渲染完成”信號后,就進(jìn)入激活狀態(tài)既程序的正常運(yùn)行狀態(tài),并調(diào)用自定義的onReady()函數(shù)。
此狀態(tài)下就可以通過 this.setData 函數(shù)發(fā)送界面數(shù)據(jù)給界面線程進(jìn)行局部渲染,更新頁面
后臺運(yùn)行狀態(tài):如果界面進(jìn)入后臺,服務(wù)線程就進(jìn)入后臺運(yùn)行狀態(tài),從目前的官方解讀來說,這個(gè)狀態(tài)挺奇怪的,和激活狀態(tài)是相同的,也可以通過setdata函數(shù)更新界面的
總結(jié)一下 小程序的一生打開小程序 -> app.onLaunch -> app.onShow -> Page.onLoad -> Page.onShow -> Page.onReady
進(jìn)入下一個(gè)頁面 -> Page.onHide -> Next.onLoad -> Next.onShow -> Next.onReady
返回上一個(gè)頁面 -> Next.onUnload -> Page.onShow
離開小程序 -> app.onHide
再次進(jìn)入 -> app未銷毀 ->app.onShow 否則從頭開始(銷毀判斷看上文運(yùn)行機(jī)制)
注意:Tabbar頁面初始化之后不會被銷毀,也就是只會執(zhí)行一次 onLoad 函數(shù)
只觸發(fā)一次的,一般都是用來初始化操作onLaunch:初始化全局?jǐn)?shù)據(jù),注意異步問題
onLoad:初始化頁面數(shù)據(jù)
onReady:代表頁面已經(jīng)準(zhǔn)備妥當(dāng),界面內(nèi)容的修改,最好放在這里,如wx.setNavigationBarTitle
onUnload:清除定時(shí)器,因?yàn)樗许撁娴哪_本邏輯都跑在同一個(gè)JsCore線程
觸發(fā)多次的,一般用來改變狀態(tài)onShow:刷新
onHide:重置
參考文獻(xiàn)http://www.wxapp-union.com/ar...
http://www.wxapp-union.com/ar...
https://developers.weixin.qq....
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100727.html
摘要:傳輸時(shí)間與數(shù)據(jù)量大體上呈現(xiàn)正相關(guān)關(guān)系,傳輸過大的數(shù)據(jù)將使這一時(shí)間顯著增加。小程序不管從組件化開發(fā)調(diào)試發(fā)布灰度回滾上報(bào)統(tǒng)計(jì)監(jiān)控和最近的云能力都非常完善,小程序的工程化簡直就是前端的典范。 研究背景 上一篇文章了解了小程序的生命周期,接下來研究一下數(shù)據(jù)通信,我覺得清楚了生命周期和數(shù)據(jù)通信,就能對整個(gè)程序有一定的把控能力,定位問題和解決問題的能力將大幅提高我剛開始擼小程序的時(shí)候,覺得看看文...
摘要:天氣預(yù)報(bào)小程序說了很多小程序開發(fā)的基礎(chǔ)準(zhǔn)備,下面就結(jié)合個(gè)人實(shí)際練手項(xiàng)目天氣預(yù)報(bào)小程序簡單說明。物料準(zhǔn)備從需求結(jié)果導(dǎo)向,天氣程序首先要能獲取到當(dāng)前所在地天氣狀況,再次可以自由選擇某地,知道其天氣狀況。 前言 學(xué)習(xí)了一段時(shí)間小程序,大致過了兩遍開發(fā)文檔,抽空做個(gè)自己的天氣預(yù)報(bào)小程序,全當(dāng)是練手,在這記錄下。小程序開發(fā)的安裝、注冊和接入等流程就不羅列了,在小程序接入指南已經(jīng)寫得很清楚了,以下...
摘要:傳統(tǒng)的網(wǎng)頁編程采用的三劍客來實(shí)現(xiàn),在微信小程序中同樣有三劍客。觀察者模式不難實(shí)現(xiàn),重點(diǎn)是如何在微信小程序中搭配其特有的生命周期來使用。交互事件傳統(tǒng)的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權(quán)網(wǎng)易云社區(qū)發(fā)布。 簡介為了更好的展示我們即時(shí)通訊SDK強(qiáng)悍的能力,網(wǎng)易云信IM SDK微信小程序DEMO的開發(fā)就提上了日程。用產(chǎn)品的話說就是: 云信 IM 小程序 S...
摘要:入口文件繼承自組件基類,它同樣擁有組件生命周期,但因?yàn)槿肟谖募奶厥庑裕纳芷诓⒉煌暾?,如。支持組件化開發(fā),組件代碼可以放在任意位置,不過建議放在下的目錄中。 生命周期 componentWillMount 在微信小程序中這一生命周期方法對應(yīng)頁面的onLoad或入口文件app中的onLaunch componentDidMount 在微信小程序中這一生命周期方法對應(yīng)頁面的onRe...
閱讀 3711·2023-04-25 22:43
閱讀 3706·2021-09-06 15:15
閱讀 1332·2019-08-30 15:54
閱讀 3543·2019-08-30 14:20
閱讀 2884·2019-08-29 17:16
閱讀 3117·2019-08-29 15:28
閱讀 3397·2019-08-29 11:08
閱讀 1071·2019-08-28 18:05