微信小程序開發簡易教程 基本知識與概念

微信小程序開發,入門算是非常簡單,只要看官文文檔即可小程序簡易教程。如何申請小程序賬號,如何開發自己第一個小程序,如何發佈,這一系列hello world操作官方文檔都有手把手教學。小程序開發的每個步驟,提供的能力文檔裡都有,個人覺得,做小程序開發,有事沒事都看下文檔,因為小程序更新比較快速,同時一些細小的能力我們可能會漏掉,所以多看文檔。

1.1 簡單說下目錄結構和app.json


文件目錄結構很靈活

先來看看小程序項目的文件目錄結構

微信小程序開發簡易教程 基本知識與概念

文件目錄結構

除了app.json必須位於根目錄下,其他文件隨意,並且都可以刪。並且頁面文件可以放到如何位置,只要在app.json中的pages中配置了就可以。可以說是很靈活。你還可以多個頁面放在同個文件夾下(我相信你不會這樣做的,何必糟蹋自己呢)。

微信小程序開發簡易教程 基本知識與概念

接下來簡單介紹下各個文件:

全局配置文件app.json

對於一個小程序項目而言,最重要的文件是app.json,它也是開發工具識別一個文件夾是否為小程序項目的標識。當使用開發者工具創建一個項目是,如果選擇的是空文件夾,它會創建一個新的項目。如果是一個有文件的文件夾,它會看該文件夾中是否有app.jon文件,如果有,則它會認為是一個小程序項目,則會打開該項目,如果文件夾中沒有app.json文件,則提示無法創建項目。

微信小程序開發簡易教程 基本知識與概念

app.json必須放置於項目的根目錄下,它是小程序項目的全局配置文件。在小程序代碼包準備完成進行啟動後(下文會詳細介紹小程序從用戶點擊打開小程序到小程序銷燬的整個過程),會先讀取app.json文件,進行小程序的初試化,比如初始化整個小程序外框樣式,獲取首頁頁面地址等。

其實小程序就是微信提供的一個容器,各個頁面就在這個容器里加載運行銷燬

下面介紹下小程序的全局配置選項:

注意:

  • 所有配置項key必須使用雙引號括起來,value值為字符串類型的也必須使用雙引號,不支持單引號
  • 因為小程序功能迭代非常迅速,基礎庫版本更新也很快,所以下面的介紹是截止目前的最新版本庫2.4.0
  • pages
 "pages": [
"pages/index/index",
"pages/log/log"
]

在app.json中,pages選項是必須配置的。該配置項註冊了小程序所有頁面的地址,其中每一項都是頁面的 路徑+文件名 。配置的字符串其實就是每個頁面wxml路徑,去掉.wxml後綴。因為框架會自動去尋找路徑下.json、.js、.wxml、.wxss四個文件進行整合。也就意味著.json、.js、.wxss這三個文件的文件名必須要和.wxml的一致,否則不生效。所以一個頁面至少必須得有.wxml文件。

總結:

  • 頁面的.json、.js、.wxss文件必須與.wxml文件同名,否則不生效
  • 每個頁面都必須pages下注冊,沒有註冊的頁面,如果不訪問,編譯能通過,一旦試圖訪問該頁面則會報錯
  • 可以通過在pages下添加一個選項快速新建一個頁面,開發工具會自動生成對應的文件
  • window
 "window":{
"enablePullDownRefresh": ture,
"navigationStyle": "custom"
}

該配置項用於配置小程序的全局外觀樣式,具體請查閱文檔。這裡重點提一下兩個比較實用的

//去掉默認的導航欄,輕鬆實現全面屏
"navigationStyle": "custom" ,
//開啟自帶的下拉刷新,減少自己寫樣式
"enablePullDownRefresh": ture,
  • tabBar

該選項可以讓我們輕鬆實現導航欄tab效果,不過有個不足就是跳轉可操作性非常低。就是每個tab只能跳當前小程序頁面,不同跳到其他小程序。如果需要跳到其他小程序,還需自己封裝個組件。

  • networkTimeout

這是網絡請求超時時間,可以設置不同類型請求的超時時間,比如wx.request、wx.uploadFile等。其實很多時候我們都會忽略這個選項,小程序默認是60s超時,但我們應該手動設置更低的值,因為我們的接口一般都會在10s內完成請求(如果超過10s,那你是時候優化了),所以如果網絡或者服務器出問題了,那麼會讓用戶等60s,最後還是失敗,這對用戶很不友好,還不如提前告訴用戶,現在出問題了,請稍後再試。

前段時間由於公司服務器網關出現了點小問題,導致有些請求連接不上,出現大量連接超時。通過之前添加的錯誤信息收集插件(這個是性能優化,下文有講到)看到了很多接口返回time-out 60s。讓用戶等了60s還是失敗,這不友好。所以這個超時時間一般設置15s-30s比較好。

  • debug

是否開啟debug功能,開啟後查看更多的調試信息,方便定位問題,開發階段可以考慮開啟

  • functionalPages

這個是結合插件使用的,因為微信小程序插件有很大限制,插件裡提供的api很有限,wx.login 和 wx.requestPayment 在插件中不能使用,如果需要獲取用戶信息和進行支付,就必須通過插件提供的功能也實現。當你的小程序下的插件啟用了插件功能也時,必須設置該選項為true

小程序插件必須掛載在一個微信小程序中,一個小程序也只能開通一個插件。當你小程序開通的插件啟用了插件功能也時,必須設置該選項為true

  • plugins
 "plugins": {
"myPlugin": {
"version": "1.0.0",
"provider": "wxidxxxxxxxxxxxxxxxx"
}
}

當小程序使用了插件就必須在這裡聲明引入。小程序自身開通的小程序不能在本身應用

  • navigateToMiniProgramAppIdList
 "navigateToMiniProgramAppIdList": [
"wxe5f52902cf4de896"
]

之前小程序之間只要是關聯了通過公眾號就可以相互跳轉,如今微信做出了限制,要這個這裡配置好需要跳轉的小程序,上限為10個,還必須寫死,不支持配置。所以當小程序有跳轉到其他小程序,一定要配好這個,否則無法跳轉。

  • usingComponents
 "usingComponents": {
"hello-component": "plugin://myPlugin/hello-component"
}

使用自定義組件或者插件提供的組件前,必須先在這裡聲明

1.2 小程序啟動與生命週期


下面來說說小程序從用戶點擊打開到銷燬的整個過程。用圖說話更清晰,特地畫了個流程圖:

微信小程序開發簡易教程 基本知識與概念

小程序啟動會有兩種情況,一種是「冷啟動」,一種是「熱啟動」。 假如用戶已經打開過某小程序,然後在一定時間內再次打開該小程序,此時無需重新啟動,只需將後臺態的小程序切換到前臺,這個過程就是熱啟動;冷啟動指的是用戶首次打開或小程序被微信主動銷燬後再次打開的情況,此時小程序需要重新加載啟動。

上面的流程圖包含了所有內容,但畢竟文字有限,接下來詳細說下幾個點。

  1. 小程序會先檢測本地是否有代碼包,然後先使用本地代碼包進行小程序啟動,再異步去檢測遠端版本。這就是小程序的離線能力,相對於H5,這是優點,能加快小程序啟動速度。
  2. 當本地有小程序代碼包時,會異步去請求遠端是否有最新版本。有則下載到本地,但該次的啟動還是會用之前的代碼。所以當我們發佈了最新的版本,需要用戶兩次冷啟動,才能使用到最新版本。如果想要用戶一次冷啟動就可以使用到最新版本,可以使用小程序提供的版本更新API更新。代碼如下,只要在app.js的onShow函數加上以下代碼,每次小程序有更新,都會提示用戶更新小程序。不過這個每次提示更新,一定程度上影響用戶體驗。如果結合後端配置,每次進來讀取配置,就可以實現根據需要是否進行該版本的更新,比如一定需要用戶更新才能使用的,那就使用強制更新。對於一些小版本,就不需要使用這個強制更新。
 if (wx.canIUse('getUpdateManager')) {
//檢測是否有版本更新
var updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 請求完新版本信息的回調,有更新
if (res.hasUpdate) {
wx.showLoading({
title: '檢測到新版本',
})
}
})
updateManager.onUpdateReady(function () {
wx.hideLoading();
wx.showModal({
title: '更新提示',
content: '新版本已經準備好,是否重啟應用?',
success: function (res) {
if (res.confirm) {
//清楚本地緩存
try {
wx.clearStorageSync()
} catch (e) {
// Do something when catch error
}
// 新的版本已經下載好,調用 applyUpdate 應用新版本並重啟
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新的版本下載失敗
console.log('新版本下載失敗');
})
}

1.3 開發工具


對於小程序開發工具,還沒有一款讓開發者滿意的工具,至少我不滿意,哈哈哈!微信提供的微信開發者工具。除了編譯器不行外,其他都還行。但由於開發工具、ios、android三個平臺運行小程序的內核不同。所以有時會出現開發工具上沒問題,真機有問題的情況,特別是樣式,可以通過在開發工具中設置上傳代碼時樣式自動補全來解決大多數問題。另外微信開發者工具提供了真機調試功能,該功能對真機調試非常方便

還有就是可以自定義編譯條件

微信小程序開發簡易教程 基本知識與概念

可以模擬任意場景值、設置頁面參數、模擬更新等。基本滿足了所有的調試。不過還有一些效果,開發工具和真機可能會不同,所以還是需要在真機上確認。

1.4 測試-審核-上線的那些事


服務器域名request合法域名每個月只能修改5次。所以不應該每次請求一個新域名就添加一次。在開發階段,在微信開發者工具上勾上不校驗合法域名,真機上需要開啟調試模式,就可以先不配置合法域名的情況下請求任何域名甚至ip地址。待開發完成了,再一次性配置所有合法域名,在微信開發者工具上取消不校驗合法域名,真機上關閉調試模式,然後開始測試。

使用體驗版+線上環境的接口,這就是和線上環境一模一樣的,所以在發佈前,使用體驗版+線上環境過一遍。如果沒問題,發佈以後也就沒問題了。

小程序二維碼只要發佈了線上版本調用生成小程序二維碼接口才能成功返回二維碼。而且二維碼識別是線上版本,所以還未發佈的小程序是無法生成二維碼的。

線上版本有個版本回退功能,這裡有個坑,就是版本回退以後,退回的版本需要重新審核才能發佈

微信小程序開發簡易教程 基本知識與概念

還有設置體驗版時可以設置指定路徑和參數,這樣很方便測試

微信小程序開發簡易教程 基本知識與概念

2 重點介紹幾個組件


接下來說說使用頻率比較多,功能強大,但又有比較多坑的幾個組件

2.1 web-view


web-view的出現,讓小程序和H5網頁之前的跳轉成為了可能。通過把H5頁面放置到web-view中,可以讓H5頁面在小程序內運行。同時在H5頁面中也可以跳轉回小程序頁面。可以說是帶來了很大的便利,但同時由於web-view的諸多限制,用起來也不是很舒服。

  • 需要打開的H5頁面必須在後臺業務頁面中配置,這其中還有個服務校驗。另外H5頁面必須是https協議,否則無法打開
  • web-view中無法在頁面中調起分享,如果需要分享,比如跳回小程序原生頁面
  • 小程序與web-view裡H5通信問題。小程序向web-view傳遞,不敏感信息可以通過頁面url傳遞。如果是敏感信息比如用戶token等,可以讓服務端重定向,比如請求服務端一個地址,讓他把敏感信息寫在cookie中,再重定向到我們的H5頁面。之後H5頁面就可以通過在cookie中拿這些敏感數據了,或者http-only,發送請求時直接帶上。
  • 每次web-view中src值有變化就會重新加載一次頁面。所以個src拼接參數時,需要先賦值給個變量拼接好再一次性setData給web-view的src,防止頁面重複刷新
  • 從微信客戶端6.7.2版本開始,navigationStyle: custom對<web-view>組件無效。也就意味著使用web-view時,自帶的導航欄無法去掉。/<web-view>
  • 因為導航欄無法去掉,這裡就出現了一個巨大的坑。實現全屏效果問題。如果想要實現H5頁面全屏,就是不滑動,全屏顯示完所有內容。這時如果你使用width:100%;height:100%,你會發現,你頁面底部可能會缺失一段。上圖:
微信小程序開發簡易教程 基本知識與概念

因為web-view是默認鋪滿全屏的,也就是web-view寬高和屏幕寬高一樣。然後H5頁面這是高度100%,這是相對web-view的高度,也是屏幕高度。但是關鍵問題:web-view裡H5頁面是從導航欄下開始渲染的。這就導致了H5頁面溢出了屏幕,無法達到全屏效果。

解決方法

這個問題我在前段時間的實際項目碰到過,我們要做個H5遊戲,要求是全屏,剛開始我也是設置高度100%。後來發現底部一塊不見了。我的解決方法比較粗暴,如果有更好的解決方法,歡迎評論交流。

我的解決方法是:通過拼接寬高參數在H5頁面url上,這個寬高是在web-view外層計算好的。H5頁面直接讀取url上的寬高,動態設置頁面的寬高。頁面高度的計算,根據上圖,很顯然就是屏幕高度減去導航欄高度。寬度都是一樣的,直接是屏幕寬度。

但問題又來了,貌似沒有途徑獲取導航欄高度。而且對於不同機型的手機,導航欄高度不同。經過了對多個機型導航欄跟屏幕高度的比較。發現了一個規律,導航欄高度與屏幕高度、屏幕寬高比有一定的關係。所以根據多個機型就計算出了這個比例。這解決了95%以上手機的適配問題,只有少數機型適配不是很好。到基本實現了全屏效果。具體代碼如下:

onLoad (options) {
//同步獲取屏幕信息,現在用到的是屏幕寬高
var res = wx.getSystemInfoSync();
if (res) {
var widHeight = res.screenHeight;
//對於大多數手機,屏幕高度/屏幕寬度 = 1.78。此時導航欄佔屏幕高度比為0.875
var raito = 0.875;
if (res.screenHeight / res.screenWidth > 1.95) {
//對於全屏手機,這個佔比會更高些
raito = 0.885;
} else if (res.screenHeight / res.screenWidth > 1.885) {
raito = 0.88;
}
//做兼容處理,只有微信版本庫高於6.7.2,有導航欄才去兼容,否則可以直接使用高度100%。res.statusBarHeight是手機頂部狀態欄高度
//如果微信版本號大於6.7.2,有導航欄
if (util.compareVersion(res.version, "6.7.2") > 0) {
widHeight = Math.round(widHeight * raito) + (res.statusBarHeight || 0);
}
this.setDate({
//將H5頁面寬高拼接在url上,賦值給web-view的src即可加載出H5頁面
webview_src: util.joinParams(h5_src, {
"height": widHeight,
"width": res.screenWidth
})
})
}
}

2.2 scroll-view


當我們要實現一個區域內滑動效果時,在H5頁面中我們設置overflow-y: scroll即可。但在小程序中,沒有該屬性。需要用到scroll-view標籤。具體操作實現我們可以查看文件scroll-view。

錨點定位在前端開發中會經常用到,在H5頁面中,我們會在url後面加上#來實現錨點定位效果。但是在小程序中這樣是不起作用的,因為小程序內渲染頁面的容易不是一個瀏覽器,無法實時監聽Hash值得變化。但是使用scroll-view,我們可以實現錨點點位效果。主要是使用scroll-into-vie屬性具體實現我們直接上代碼

scroll-into-view | String | 值應為某子元素id(id不能以數字開頭)。設置哪個方向可滾動,則在哪個方向滾動到該元素

wxml文件

 
<scroll-view> scroll-with-animation = "true" style="height: 100%; white-space:nowrap">
<view>
<view>
<view>
<scroll-view>
/<scroll-view>/<scroll-view>

2.3 canvas


畫布標籤,它是原生組件,所以它必須位於屏幕最上邊,而且是不能隱藏的。所以如果想要使用canvas動態生成分享照片。那你要設置她的寬高和屏幕一樣。要不導出為照片時就會失真。因為這個原因,所以生成分享照片還是有服務端實現吧,照片失真太嚴重了。

3 formid收集


給用戶發送消息對一個小程序是非常重要的,它可以召喚回用戶,導量效果非常明顯。我們可以通過模板消息想小程序用戶發送消息,但前提是我們得獲取到openid和formid。用戶登錄我們即可即可獲取到用戶openid。而只要用戶有點擊行為,我們即可獲取到formid獲取formid。所以說formid是很重要的。我們可以提前收集好formid,在需要的時候給用戶推送消息。我們可以個每個button都包上form標籤,只要有用戶點擊行為都可以收集到formid.

 

我們實現一個formid收集系統,為了儘量減少冗餘代碼和減少對業務的影響,我們的設計是這樣的

  1. 在整個頁面的最外層包裹form標籤,不是每個button都包裹一個,這樣只要是頁面中formTpye=submit的button有點擊都能獲取到formid。
  2. formid保存在全局變量數組中,當小程序切換到後臺是一次性發送。
  3. 對於需要實時發送消息的,不添加值全局數組中,直接保存在頁面變量中。

wxml文件

 

page.js文件

 //每次用戶有點擊,都將formid添加到全局數組中
formSubmit(e) {
//需要實時發送的,不添加
if(e.target.dataset.sendMsg){
formid = e.detail.formId;
return;
}
app.appData.formIdArr.push(e.detail.formId);
}

app.js

 onHide: function () {
//小程序切到後臺時上傳formid
this.submitFormId();
},

4 性能優化相關


從用戶打開小程序到小程序銷燬,我們可以想想有哪些地方是可以優化的。首先是打開速度。小程序打開速度直接影響了用戶留存。在小程序後臺,運維中心-監控告警下有個加載性能監控數據,我們可以看到小程序啟動總耗時、下載耗時、首次渲染耗等加載相關的數據。而這裡的打開速度其實就是小程序的啟動總耗時。它包括了代碼包下載、首次渲染,微信內環境初始化等步湊。在這一步,我們能做的就是

如何加快代碼包下載速度和減少首次渲染時間

在小程序呈現給用戶之後,接下來如何提高用戶體驗,增強小程序健壯性的問題了。每個程序都有bug。只是我們沒發現而已,儘管在測試階段,我們進行了詳盡的測試。但是在實際生產環境,不同的用戶環境,不同的操作路徑,隨時會觸發一些隱藏的bug。這時如果用戶沒有向我們報告,我們是無法獲知的。所以有必要給我們的小程序增加錯誤信息收集,js腳本錯誤,意味著整個程序掛掉了,無法響應用戶操作。所以對於運行時的腳本錯誤,我們應該上報。對出現的bug及時修復,增強程序健壯性,提供用戶體驗。

每個程序都有大量的前後端數據交互,這是通過http請求進行的。因此,還有一個錯誤信息收集就是接口錯誤信息收集。對那些請求狀態碼非2XX、3XX的,或者請求接口成功了,但是數據不是我們預期的,都可以進行信息採集。

通過對小程序運行時腳本和http請求進行監控,我們就可以實時瞭解我們線上小程序的運行狀況,有什麼問題可以及時發現,及時修復,極高地提高了用戶體驗性。

4.1 讓小程序更快


讓小程序快,主要因素有兩個,代碼包下載和首屏渲染。

我們來看一個數據:

微信小程序開發簡易教程 基本知識與概念

前面狀態小程序代碼大小是650Kb左右,這是下載耗時(雖然跟用戶網絡有關,但這個是全部用戶平均時間)是1.3s左右。但是經過優化,將代碼包降低至200kb左右時。下載耗時只有0.6s左右。所以說,代碼包減少500kb,下載耗時能減少0.5s。這個數據還是非常明顯和。所以說,在不影響業務邏輯的情況下,我們小程序代碼包應該儘可能地小。那麼如何降低代碼包大小呢?以下有幾點可以參考

  1. 因為我們上傳代碼到微信服務器時,它會將我們的代碼進行壓縮的,所以用戶下載的代碼包並不是我們開發時的那個大小。對此,開發時也沒必要刪空行、刪註釋這些。在開發工具項目詳情中可以看到上次上傳大小,這個大小就是用戶最終使用的大小。如果覺得微信壓縮還不夠好,可以通過第三方工具對我們代碼進行一次壓縮再上傳,然後對比效果,有沒有更小。這個沒有使用過。如果有什麼好工具,歡迎推薦。
  2. 將靜態資源文件防止到我們自己服務器或者cdn上。一個小程序,最耗空間的往往是圖片文件。所以我們可以抽離出來,圖片文件可以異步獲取,在小程序啟動以後再去獲取。這樣,代碼包就會小很多。
  3. 使用分包加載。小程序提供了分包加載功能。如果你的小程序很龐大,可以考慮使用分包加載功能,先加載必要功能代碼。這樣就是可以極大降低代碼包大小

接下來是首屏渲染,從上圖的小程序生命週期可以看出,從加載首頁代碼帶首頁完成渲染,這段時間就是白屏時間,也就是首次渲染時間。而小程序在這段時間內,主要工作是:加載首頁代碼、創建View和AppService層、初試數據傳輸、頁面渲染。在這四個步驟中,加載首頁代碼,前面已經說過;創建View和AppService層,是微信完成的,跟用戶手機有關,這不是我們可控的。我們能做的就是減少初試數據傳輸時間和頁面渲染時間。

  1. 我們知道page.js中的data對象在首次渲染時會通過數據管道傳個視圖層進行頁面渲染。所以我們應該控制這個data對象的大小。對於與視圖渲染無關的數據,不要放在data裡面,可以設置個全局變量來保存。
 Page({
//與頁面渲染有關的數據放這裡
data: {
goods_list:[]
},
//與頁面渲染無關的數據放這裡
_data: {
timer: null
}
})
  1. 頁面渲染速度還跟html的dom結構有關。這一點的優化空間算是非常少了,就是寫高質量html代碼,減少dom嵌套,讓頁面渲染速度快一丟丟。

4.2 讓小程序更強


接下來就是給小程序增加錯誤信息收集,包括js腳本錯誤信息收集和http請求錯誤信息收集。前段時間,在時間工作開發中,為了更好的複用和管理,我把這個錯誤信息收集功能做成了插件。然而做成插件並沒有想象中的那麼美好,下面再具說。

腳本錯誤收集

對於腳本錯誤收集,這個相對比較簡單,因為在app.js中提供了監聽錯誤的onError函數

微信小程序開發簡易教程 基本知識與概念

只不過錯誤信息是包括堆棧等比較詳細的錯誤信息,然後當上傳時我們並不需要這麼信息,第一浪費寬帶,第二看著累又無用。我們需要的信息是:錯誤類型、錯誤信息描述、錯誤位置。

thirdScriptError
aa is not defined;at pages/index/index page test function
ReferenceError: aa is not defined
at e.test (http://127.0.0.1:62641/appservice/pages/index/index.js:17:3)
at e.<anonymous> (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:31500)
at e.a (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:26386)
at J (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:20800)
at Function.<anonymous> (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:22389)
at http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:27889
at http://127.0.0.1:62641/appservice/__dev__/WAService.js:6:16777
at e.(anonymous function) (http://127.0.0.1:62641/appservice/__dev__/WAService.js:4:3403)
at e (http://127.0.0.1:62641/appservice/appservice?t=1543326089806:1080:20291)
at r.registerCallback.t (http://127.0.0.1:62641/appservice/appservice?t=1543326089806:1080:20476)
/<anonymous>/<anonymous>

這是錯誤信息字符串,接下來我們對它進行截取只需要拿我們想要的信息即可。我們發現這個字符串是有規則的。第一行是錯誤類型,第二行是錯誤詳情和發生的位置,並且是";"分好分開。所以我們還是很容易就可以拿到我們想要的信息。

 //格式化錯誤信息
function formateErroMsg(errorMsg){
//包一層try catch 不要讓信息收集影響了業務
try{
var detailMsg = '';
var detailPosition= '';
var arr = errorMsg.split('\n')
if (arr.length > 1) {
//錯誤詳情和錯誤位置在第二行並用分好隔開
var detailArr = arr[1].split(';')
detailMsg = detailArr.length > 0 ? detailArr[0] : '';
if (detailArr.length > 1) {
detailArr.shift()
detailPosition = detailArr.join(';')
}
}
var obj = {
//錯誤類型就是第一行

error_type: arr.length > 0 ? arr[0] : '',
error_msg: detailMsg,
error_position: detailPosition
};
return obj
}catch(e){}
}

獲取到我們想要的信息,就可以發送到我們服務後臺,進行數據整理和顯示,這個需要服務端配合,就不深入講了,我們拿到了數據,其他都不是事。

http請求錯誤信息收集

對於http請求錯誤信息收集方式,我們儘量不要暴力埋點,每個請求發送前發送後加上我們的埋點。這樣工作量太大,也不易維護。因此,我們可以從底層出發,攔截wx.request請求。使用Object.definePropert對wx對象的request進行重新定義。具體實現如下

function rewriteRequest(){
try {
const originRequest = wx.request;
Object.defineProperty(wx, 'request', {
configurable:true,
enumerable: true,
writable: true,
value: function(){
let options = arguments[0] || {};
//對於發送錯誤信息的接口不收集,防止死循環
var regexp = new RegExp("https://xxxx/error","g");
if (regexp.test(options.url)) {
//這裡要執行原來的方法

return originRequest.call(this, options)
}
//這裡攔截請求成功或失敗接口,拿到請求後的數據
["success", "fail"].forEach((methodName) => {
let defineMethod = options[methodName];
options[methodName] = function(){
try{ //在重新定義函數中執行原先的函數,不影響正常邏輯
defineMethod && defineMethod.apply(this, arguments);
//開始信息收集
let statusCode, result, msg;
//請求失敗
if (methodName == 'fail') {
statusCode = 0;
result = 'fail';
msg = ( arguments[0] && arguments[0].errMsg ) || ""
}
//請求成功,
//收集規則為:
// 1、 statusCode非2xx,3xx
// 2、 statusCode是2xx,3xx,但接口返回result不為ok
if (methodName == 'success') {
let data = arguments[0] || {};
statusCode = data.statusCode || "";
if (data.statusCode && Number(data.statusCode) >= 200 && Number(data.statusCode) < 400 ) {
let resData = data.data ? (typeof data.data == 'object' ? data.data : JSON.parse(data.data)) : {};
//請求成功,不收集
if (resData.result == 'ok') {
return;
}
result = resData.result || "";
msg = resData.msg || "";
}else{
result = "";
msg = data.data || "";
}
}
//過濾掉header中的敏感信息
if (options.header) {
options.header.userid && (delete options.header.userid)
}
//過濾掉data中的敏感信息

if (options.data) {
options.data.userid && (delete options.data.userid)
}

var collectInfo = {
"url": options.url || '', //請求地址
"method": options.method || "GET", //請求方法
"request_header": JSON.stringify(options.header || {}), //請求頭部信息
"request_data": JSON.stringify(options.data || {}), //請求參數
"resp_code": statusCode + '', //請求狀態碼
"resp_result": result, //請求返回結果
"resp_msg": msg, //請求返回描述信息
}
//提交參數與上一次不同,或者參數相同,隔了1s
if (JSON.stringify(collectInfo) != lastParams.paramStr || (new Date().getTime() - lastParams.timestamp > 1000)) {
//上傳錯誤信息
Post.post_error(_miniapp, 'http', collectInfo)
lastParams.paramStr = JSON.stringify(collectInfo);
lastParams.timestamp = new Date().getTime()
}
}catch(e){
//console.log(e);
}
};
})
return originRequest.call(this, options)
}
})
} catch (e) {
// Do something when catch error
}
}

在不使用插件的小程序中,我們可以在使用wx.request方法執行上面的代碼,對wx.request進行攔截,然後其他無需加任何代碼就可以收集http請求了。

上面說了,當我們封裝成到插件時,這個就不管用了,因為當使用插件時,小程序不允許我們修改全局變量。所以執行上面代碼時會報錯。這時,我們退而求其次,只能是在插件中自己封裝個方法,這個方法其實就是wx.request發送請求,但是在插件中我們就有可以攔截wx.request了。具體實現如下:

 function my_request(){
//只要執行一次攔截代碼即可
!_isInit && rewriteRequest();
return wx.request(options)
}

接下來我們看下後臺數據

微信小程序開發簡易教程 基本知識與概念

微信小程序開發簡易教程 基本知識與概念

持續監控,會幫我們找出很多隱藏的bug

4 總結


洋洋灑灑寫了這麼多,或許有些地方說的不太清楚,慢慢鍛鍊吧。然後後面幾點只是挑了重要的講,我相信有過小程序開發經驗的朋友應該沒問題。然後有時間再補充和優化了。先到此,有緣看到的朋友,歡迎留言交流。

基本微信小程序開發本身也不是一件簡單的事情,現在說的也不夠詳細,想要開發出一款成功的小程序還是要付出很多的精力,當然也可以選擇小程序開發公司,這樣是會省去很多麻煩。這裡安利一個鈺威軟件,一家擁有成熟穩定技術的團隊,目前已經和很多企業達成合作,開發了很多的APP、小程序的產品,無論是淘寶電商、餐飲娛樂、本土企業都可以找到適合自己的軟件APP,打造一款適合自己的線上手機端,真正實現趕上智能商業步伐的途徑。


分享到:


相關文章: