微信小程序的優(yōu)化技巧有哪些、優(yōu)化方法
hishop表示小程序科普類的文章已經(jīng)很多了,這里講下針對小程序的優(yōu)化方法,可以有效提高小程序的響應(yīng)速度和用戶體驗(yàn)。當(dāng)然,開發(fā)體驗(yàn)也提高不少。
1、提高頁面加載速度——前端永恒不變的話題
在小程序這個(gè)環(huán)境下,怎樣提高頁面加載速度呢? 這個(gè)問題很大,我把問題具體一下,如何縮短從用戶點(diǎn)擊某個(gè)鏈接,到打開新頁面的這段時(shí)間? 這里拋一個(gè)核心關(guān)鍵點(diǎn):
從頁面響應(yīng)用戶點(diǎn)擊行為,開始跳轉(zhuǎn),到新頁面onload事件觸發(fā),存在一個(gè)延遲,這個(gè)延遲大概在100-300ms之間(安卓響應(yīng)比ios慢些)。
這個(gè)延遲說短不短,我們可以利用這段時(shí)間,預(yù)先發(fā)起新頁面所需要的網(wǎng)絡(luò)請求。這樣一來,就節(jié)省了100-300ms(或者一個(gè)網(wǎng)絡(luò)請求的時(shí)間)。
知道有這個(gè)gap后,代碼如何實(shí)現(xiàn)呢?
說白了,就是實(shí)現(xiàn)一個(gè)在A頁面預(yù)加載B頁面數(shù)據(jù)的功能。但而這種跨頁面的調(diào)用,很容易把邏輯搞復(fù)雜,將不同頁面的邏輯耦合在一起。所以,我們希望將預(yù)加載的邏輯隱藏于無形中,不增加任何的頁面間耦合,以及開發(fā)復(fù)雜度。
下面以騰訊視頻小程序?yàn)槔?,講解下技術(shù)實(shí)現(xiàn)。
onPlay: function (e) {
this.$route('/pages/play/index?cid='+this._cid);
}
接下來程序會加載播放頁:
接下來程序會加載播放頁:
fetchData: function (query) {
},
onNavigate: function (res) {
this.$put('play-detail', this.fetchData(res.query));
},
onLoad: function (query) {
this.$take('play-detail') || this.fetchData(query);
}
可以看到,不管是外部頁面的調(diào)用還是實(shí)際邏輯的實(shí)現(xiàn)都非常簡潔。在第二個(gè)頁面中,我們擴(kuò)展了Page的生命周期函數(shù),增加了onNavigate方法。該方法在頁面即將被創(chuàng)建但還沒開始創(chuàng)建的時(shí)候執(zhí)行。
老司機(jī)也許會發(fā)現(xiàn)這里有點(diǎn)蹊蹺。在首頁點(diǎn)擊的時(shí)候,播放頁根本就沒有創(chuàng)建,對象都不存在,怎么訪問到里面的方法呢?
這里就要說下微信的頁面機(jī)制。
在小程序啟動時(shí),會把所有調(diào)用Page()方法的object存在一個(gè)隊(duì)列里(如下圖)。每次頁面訪問的時(shí)候,微信會重新創(chuàng)建一個(gè)新的對象實(shí)例(實(shí)際上就是深拷貝)。也就是說,在A頁面在執(zhí)行點(diǎn)擊響應(yīng)事件的時(shí)候,B頁面的實(shí)例還沒創(chuàng)建,這時(shí)候調(diào)用的onNavigate方法,實(shí)際上是Page對象的原型(小程序啟動時(shí)候創(chuàng)建的那個(gè))。而接下來馬上要被創(chuàng)建的B頁面,又是另外一個(gè)object。所以,在onNavigate和onLoad方法中,this指針指的不是同一個(gè)對象,不能把臨時(shí)數(shù)據(jù)存儲在當(dāng)前object身上。因此我們封裝了一對全局的緩存方法,$put()和$take()。
為了通用性,Page上用到的公共的方法,比如$route、$put、$take都定義在了一個(gè)Page的基類里面?;愡€同時(shí)保存了所有頁面的list,這樣就可以做到根據(jù)頁面名調(diào)用具體頁面的onNavigate方法。 當(dāng)然,并不是每個(gè)頁面都需要實(shí)現(xiàn)onNavigate方法,對于沒有定義onNavigate方法的,$route函數(shù)會跳過預(yù)加載環(huán)節(jié),直接跳轉(zhuǎn)頁面。所以對于開發(fā)者來說,不需要關(guān)心別的頁面實(shí)現(xiàn)了什么,對外看來完全透明。
2、用戶行為預(yù)測
在上面的例子中,我們實(shí)現(xiàn)了用戶主動點(diǎn)擊頁面,提前加載下一頁面數(shù)據(jù)的方法。而在某些場景下,用戶的行為可以預(yù)測,我們可以在用戶還沒點(diǎn)擊的時(shí)候就預(yù)加載下個(gè)頁面的數(shù)據(jù)。讓下個(gè)頁面秒開,進(jìn)一步提升體驗(yàn)的流暢性。
繼續(xù)以騰訊視頻小程序?yàn)槔?,主界面分?個(gè)頁卡(大部分小程序都會這么設(shè)計(jì)),通過簡單的數(shù)據(jù)分析,發(fā)現(xiàn)進(jìn)入首頁的用戶有50%會訪問第二個(gè)頁卡。所以預(yù)加載第二個(gè)頁卡的數(shù)據(jù)可以很大程度提高用戶下個(gè)點(diǎn)擊頁面的打開速度。
同樣,先看看代碼實(shí)現(xiàn)。 首頁預(yù)加載頻道頁的姿勢:
onReady: function(){
//預(yù)加載頻道頁
this.$preLoad("/pages/channel/index")
}
頻道頁的實(shí)現(xiàn)方法:
onPreload: function(req){
//拉取數(shù)據(jù)
this.fetchData({
id: req.query.channelId ? req.query.channelId : defaultId,
isPreload: true
})
}
跟第一個(gè)例子類似,這里定義了一個(gè)$preLoad()方法,同時(shí)給Page擴(kuò)展了一個(gè)onPreload事件。頁面調(diào)用$preLoad()后,基類會自動找到該頁面對應(yīng)的onPreload函數(shù),通知頁面執(zhí)行預(yù)加載操作。 跟第一個(gè)例子不同,這里預(yù)加載的數(shù)據(jù)會保存在storage內(nèi),因?yàn)橛脩舨灰欢〞R上訪問頁面,而把數(shù)據(jù)存在全局變量會增加小程序占用的內(nèi)存。微信會毫不猶豫的把內(nèi)存占用過大的小程序給殺掉。
也許對于大部分有app開發(fā)經(jīng)驗(yàn)的同學(xué)來說,更普遍的做法是先讓頁面展示上次緩存的數(shù)據(jù),再實(shí)時(shí)拉取新數(shù)據(jù),然后刷新頁面。這個(gè)方法在小程序上也許體驗(yàn)并不太好,原因是小程序的性能以及頁面渲染速度都不如原生app。將一個(gè)大的data傳輸給UI層,是一個(gè)很重的操作。因此不建議采用這種方法。
3、減少默認(rèn)data的大小
剛剛說到,頁面打開一個(gè)新頁面時(shí)微信會深拷貝一個(gè)page對象,因此,應(yīng)該盡量減少默認(rèn)data的大小,以及減少對象內(nèi)的自定義屬性。有圖有真相:
以一個(gè)100個(gè)屬性的data對象為測試用例,在iphone6上,頁面的創(chuàng)建時(shí)間會因此增加150ms。
4、組件化方案
微信沒有提供小程序的組件化方案(相信一定在實(shí)現(xiàn)中)。但開談不說組件化,寫再多代碼也枉然。這里演示一個(gè)簡單的組件化實(shí)現(xiàn)。
以騰訊視頻播放頁為例,頁面定義如下:
其中,P()函數(shù)是自定義的基類。這是一個(gè)非常有用的東西,可以把所有通用的邏輯都寫在基類里面,包括pv統(tǒng)計(jì),來源統(tǒng)計(jì),擴(kuò)展生命周期函數(shù),實(shí)現(xiàn)組件化等。
函數(shù)第一個(gè)參數(shù)是頁面名稱,作為頁面的key。第二個(gè)是page對象,其中擴(kuò)展了一個(gè)comps數(shù)組,里面就是所有要加載的組件。
以播放器組件/comps/player/index.js為例:
組件的定義跟一個(gè)普通Page對象一模一樣,有data屬性,onLoad、onShow等事件,也有頁面響應(yīng)的回調(diào)方法。wxml模板里定義的事件和js事件一一對應(yīng)。
基類做的事情,就是把這些組件對象的屬性和方法復(fù)制到Page對象上(淺拷貝)。其中data屬性會merge到一起。而微信預(yù)定義的生命周期函數(shù)(包括自己擴(kuò)展的),則封裝成隊(duì)列按序執(zhí)行。比如當(dāng)系統(tǒng)調(diào)用onLoad方法時(shí),實(shí)際上是執(zhí)行了所有組件的onLoad方法,最后再執(zhí)行Page的onLoad。
以上是代碼部分,至于wxml模板和wxss部分,就要手工import過去了。
wxml:
wxss:
5、其他
雖然微信小程序(http://m.descansotropical.com/xiaocx/)已經(jīng)足夠小巧,但啟動速度還是有那么2-3秒,無法做到秒開。樓主嘗試對小程序的啟動時(shí)間做優(yōu)化,但沒有找到多少有價(jià)值的優(yōu)化點(diǎn)。單個(gè)頁面的初始化只需要1-2ms。也許大部分時(shí)間消耗在了微信跟服務(wù)器端通信的過程中。期待微信不斷迭代優(yōu)化。
第二部分:如何開通一個(gè)小商店