小程序開發(fā)常見問題實(shí)戰(zhàn)總結(jié)
本文從小程序框架、 api 、組件、應(yīng)用四個(gè)方面入手,說明在開發(fā)過程中遇到的問題,并給出處理方案。
小程序雖然具有相對(duì)完善的文檔,但難免文檔中會(huì)有解釋不清晰,不易被人發(fā)現(xiàn),甚至未曾提及的問題。本文從具體的業(yè)務(wù)場(chǎng)景出發(fā),匯總筆者在原生小程序日常開發(fā)中遇到的常見問題,并給出相應(yīng)的解決方案,希望能夠?qū)⑦@些細(xì)節(jié)經(jīng)驗(yàn)分享給需要的童鞋。
框架運(yùn)行機(jī)制與更新機(jī)制
運(yùn)行機(jī)制:
小程序啟動(dòng)會(huì)有兩種情況,一種是「冷啟動(dòng)」,一種是「熱啟動(dòng)」。 假如用戶已經(jīng)打開過某小程序,然后在一定時(shí)間內(nèi)再次打開該小程序,此時(shí)無需重新啟動(dòng),只需將后臺(tái)態(tài)的小程序切換到前臺(tái),這個(gè)過程就是熱啟動(dòng);冷啟動(dòng)指的是用戶首次打開或小程序被微信主動(dòng)銷毀后再次打開的情況,此時(shí)小程序需要重新加載啟動(dòng)。
- 小程序沒有重啟的概念。
- 當(dāng)小程序進(jìn)入后臺(tái),客戶端會(huì)維持一段時(shí)間的運(yùn)行狀態(tài),超過一定時(shí)間后(目前是5分鐘)會(huì)被微信主動(dòng)銷毀。
- 當(dāng)短時(shí)間內(nèi)(5s)連續(xù)收到兩次以上收到系統(tǒng)內(nèi)存告警,會(huì)進(jìn)行小程序的銷毀。
更新機(jī)制:
小程序冷啟動(dòng)時(shí)如果發(fā)現(xiàn)有新版本,將會(huì)異步下載新版本的代碼包,并同時(shí)用客戶端本地的包進(jìn)行啟動(dòng),即新版本的小程序需要等下一次冷啟動(dòng)才會(huì)應(yīng)用上。 如果需要馬上應(yīng)用最新版本,可以使用 wx.getUpdateManager API 進(jìn)行處理。
雖然文檔中有對(duì)這一部分進(jìn)行說明,但是隱蔽比較深,還是需要重點(diǎn)說明一下,理解運(yùn)行機(jī)制就可以解釋為什么剛關(guān)閉的小程序打開之后還能保存之前的狀態(tài),理解更新機(jī)制就明白新發(fā)版的小程序?yàn)槭裁葱枰獎(jiǎng)h除舊的版本再下載新的版本再能有新版的內(nèi)容了。
如何清除小程序緩存呢?
- 通過太空囊’…’按鈕—打開調(diào)試—console—wechat—wx.clearStorage()方法清除,此方法刪除 storage 中的數(shù)據(jù)。
- 通過微信的”發(fā)現(xiàn)”tab簽—小程序—長(zhǎng)按或者右滑刪除指定小程序,此方式徹底卸載該小程序,也就清除了所有內(nèi)容,包括 storage 中緩存數(shù)據(jù)、場(chǎng)景值、頁(yè)面堆棧等。
預(yù)覽與遠(yuǎn)程調(diào)試的區(qū)別
小程序的調(diào)試方式有多種,可以通過預(yù)覽亦可通過遠(yuǎn)程調(diào)試,這兩者有何區(qū)別呢?
將兩者生成的二維碼轉(zhuǎn)為url:
- 預(yù)覽 URL 為:https://mp.weixin.qq.com/a/~~xxt10QprXmU~rsguk7Cm9P3v2MCXJdpacg~~
- 遠(yuǎn)程調(diào)試 URL 為:https://mp.weixin.qq.com/a/~~Rot_QPKUIn8~mzI5kQoA3w4QN0H6nkejvQ~~
由此可見工作方式都為將本地小程序打包上傳至微信側(cè),掃碼訪問遠(yuǎn)程小程序服務(wù)。不同點(diǎn)總結(jié)如下:
- 可以有多臺(tái)真機(jī)同時(shí)預(yù)覽,只能有一臺(tái)真機(jī)遠(yuǎn)程調(diào)試。
- 預(yù)覽忽略斷點(diǎn),遠(yuǎn)程調(diào)試會(huì)有斷點(diǎn)。
- 預(yù)覽可以忽略部分報(bào)錯(cuò),遠(yuǎn)程調(diào)試有報(bào)錯(cuò)將無法運(yùn)行。
生命周期又分頁(yè)面的生命周期與組件的生命周期,以頁(yè)面的生命周期為例,不同的生命周期會(huì)對(duì)應(yīng)不同的生命周期方法。
- onLoad: 頁(yè)面加載,一個(gè)頁(yè)面只會(huì)調(diào)用一次。
- onShow: 頁(yè)面顯示,每次打開頁(yè)面都會(huì)調(diào)用一次。
- onReady: 頁(yè)面初次渲染完成,一個(gè)頁(yè)面只會(huì)調(diào)用一次,代表頁(yè)面已經(jīng)準(zhǔn)備妥當(dāng),可以和視圖層進(jìn)行交互。
- onHide: 頁(yè)面隱藏,當(dāng) navigateTo 或底部 tab 切換時(shí)調(diào)用。
- onUnload: 頁(yè)面卸載。
進(jìn)行頁(yè)面編碼之前需要考慮到哪些數(shù)據(jù)是只需要加載一次的(放到 onload 中),哪些數(shù)據(jù)需要每次在頁(yè)面切換出來的時(shí)候進(jìn)行實(shí)時(shí)更新(放到 onShow 中執(zhí)行)。
ApisetData:賦值操作是做常用的操作,可是對(duì)不同類型的數(shù)據(jù)賦值方式又稍有不同:
- 給字符串賦值: str:’value’
- 對(duì)象屬性賦值:[‘obj.prop’]:’value’
- 數(shù)組中的對(duì)象的屬性賦值:[‘arr[0].prop’]:’value’
需要注意的是: setData 方法為異步方法,如不注意,頁(yè)面渲染會(huì)出現(xiàn)異常,因此不要將頁(yè)面中所有的數(shù)據(jù)都放到 data 對(duì)象中,只將頁(yè)面展示層的數(shù)據(jù)放到 data 中,其他不需要展示的數(shù)據(jù)掛載到全局 this 中即可。
chooiceVideo 視頻封面問題:在 wx.chooseVideo 的回調(diào)函數(shù)中,res 中會(huì)有 thumbTempFilePath 屬性值,該屬性值為封面圖片,問題是在模擬器中可以獲取到該屬性但是在真機(jī)中無法獲取到該屬性。目前獲取封面圖的方式通常為后端處理獲取。
組件Video- 層級(jí): video 等的原生組件具有最高的層級(jí),z-index 設(shè)置無效,會(huì)出現(xiàn)提示框被 video 覆蓋,或者 fixed 在頁(yè)面某位置的圖標(biāo)被覆蓋的問題,處理方式見后文。
- 封面圖:封面圖的設(shè)置方式一般有兩種方式:通過 poster 屬性設(shè)置封面圖片,用這種方式開發(fā)工具上圖片閃一下就沒了,另一種方式是在 video 標(biāo)簽中放置 cover-view 、 cover-img ,存在問題是如果 video 寬高為300*200,img 寬高為200*150,但是這是圖片寬高為300*200(與video一致),在模擬器中沒有問題,在真機(jī)中圖片不能拉伸,而且原生的播放按鈕和時(shí)間都被覆蓋了。
- 視頻播放:想要執(zhí)行視頻播放,先要獲取視頻組件,通過 wx.createVideoContext(videoId,this) 獲取視頻對(duì)象。 文檔中說明為:
創(chuàng)建并返回 video 上下文 videoContext 對(duì)象。在自定義組件下,第二個(gè)參數(shù)傳入組件實(shí)例 this ,以操作組件內(nèi) ‘video’ 組件。
需要注意的是在自定義組件內(nèi)部需要傳第二個(gè)參數(shù),其他情況不用,同時(shí)獲取視頻組件后執(zhí)行play方法,會(huì)發(fā)現(xiàn)在模擬器中視頻不會(huì)執(zhí)行播放,困惑許久,發(fā)現(xiàn)在真機(jī)中可以執(zhí)行播放動(dòng)作,意外不意外???!趟過此坑,再一次印證了那句警世名言——“一切不在真機(jī)上驗(yàn)證的自測(cè),都是耍流氓!”
cover-viewcover-view是官方制造出來,用來管制那群“無法無天”的原生組件的,這群組件包括: map 、 video 、 canvas 、 camera 、 live-player 、live-pusher 。他確實(shí)可以蓋住這些組件,但是 cover-view 自身存在一些缺陷,令人很苦惱。
- 部分樣式效果實(shí)現(xiàn)不了:只支持基本的定位、布局、文本樣式。不支持設(shè)置單邊的 border 、background-image 、shadow 、overflow : visible 等。
- 子節(jié)點(diǎn)如果溢出了父節(jié)點(diǎn),溢出部分莫名其妙被干掉了。 建議子節(jié)點(diǎn)不要溢出父節(jié)點(diǎn)。
- 自定義組件嵌套 cover-view 時(shí),自定義組件的 slot 及其父節(jié)點(diǎn)暫不支持通過 wx:if 控制顯隱,否則會(huì)導(dǎo)致 cover-view 不顯示。
- 對(duì)于 fixed 屬性支持不好,fixed 在頁(yè)面底部的按鈕,可能會(huì)隨頁(yè)面滾動(dòng)而上下“瞬移”哦。
組件中有 scroll-left 屬性,該屬性是可以指定向左滾動(dòng)的距離,但是此距離沒有單位,不由好奇,這個(gè)距離的單位是什么,于是做如下測(cè)試:屏幕寬度為750 rpx 設(shè)置每個(gè)小塊的寬度的寬度為150 rpx ,分別在 iphone5 、iphone6 、iphone6plus 中設(shè)置scroll-left 為 150,頁(yè)面表現(xiàn)如下:
會(huì)發(fā)現(xiàn)5下滾動(dòng)超過兩個(gè)格,6下剛好兩個(gè)格,6p下小于兩個(gè)格,不難理解,scroll-left的單位為px,不同機(jī)型會(huì)有不同的表現(xiàn)是由于不同機(jī)型下單位的轉(zhuǎn)換不同導(dǎo)致的:
- iPhone6 Plus : 1rpx = 0.552px 150px = 271.5rpx
- phone6 : 1rpx = 0.5px 150px = 300rpx
- phone5 : 1rpx = 0.42px 150px = 357rpx
因此除非自己進(jìn)行單位自適應(yīng),否則 scroll-left 屬性實(shí)用性不強(qiáng)。
應(yīng)用下拉刷新問題:- 場(chǎng)景:頁(yè)面需要下拉重新加載數(shù)據(jù),刷新頁(yè)面,小程序開啟下拉刷新時(shí), Fixed 在頂部的 tabbar (橫欄)下拉時(shí),在 ios 端會(huì)出現(xiàn)斷層,并顯示背景,安卓端無此表現(xiàn)。
- 解決方案:由于安卓跟 ios 端的變現(xiàn)差異過大,因此需要避免在需要做下拉刷新的頁(yè)面放置 fixed 在頁(yè)面頂部的tabbar,可以通過自定義頁(yè)面頭部,并將該tabbar寫到自定義頭部中。
那么如何自定義頭部呢? 通過在app.js中設(shè)置navigationStyle屬性,默認(rèn)值為‘default’,自定義為‘custom’。
- 默認(rèn)頭部樣式展示如下:
- 自定義頭部樣式展示如下:
可以看到自定義頭部樣式時(shí),頭部只保留膠囊,其他部分可以自己實(shí)現(xiàn)。
視頻層級(jí)問題:- 場(chǎng)景:頁(yè)面中存在video標(biāo)簽,同時(shí)會(huì)存在彈框,并且頁(yè)面底部有fixed在底部的按鈕,這兩部分不允許video覆蓋。
- 解決方案:官方給出的覆蓋video組件的方式是,通過cover-view,但由于cover-view對(duì)樣式的支持不足及自身的問題(見上文),因此我們不使用cover-view處理。處理方式是使用圖片和video交替展示的方式,初始化展示為一張圖片,當(dāng)點(diǎn)擊播放時(shí)切換video組件進(jìn)行展示。頁(yè)面滾動(dòng),以及彈框出現(xiàn)的時(shí)候,將視頻組件隱藏,注意是隱藏,通過hidden屬性隱藏,而不是wx:if直接干掉,因?yàn)橐曨l播放中途暫停,下次播放需要從上次結(jié)束的位置開始播放,如果使用wx:if則無疑增加了實(shí)現(xiàn)的難度。
本文從框架、api、組件、應(yīng)用四個(gè)方面入手,說明在開發(fā)過程中遇到的問題,問題分析相對(duì)淺顯,但是比較實(shí)用。希望可以對(duì)讀者提供些許幫助。同時(shí)面對(duì)小程序時(shí)的心態(tài)已由最初的“純粹的api編程”到心懷敬畏之情。看似簡(jiǎn)單的表象下,會(huì)存在這一系列棘手的情況。在此處做下總結(jié),歡迎各位拍磚指正!
第二部分:如何開通一個(gè)小商店