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