用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 查看內容

04年湖人vs火箭:小程序如何做全局重新加載

湖人vs爵士季后赛 www.nbgeh.club Rolan 2019-6-4 00:44

背景:隨著業務的增加,我們服務器需要計算大量的用戶數據,導致用戶跟客服反應頁面不能正常展示。反饋給開發后,我們一看,是服務器異常的錯誤。So,產品想看下我們到底有多少用戶頁面不能正常展示?方案:后端人員 ...

背景:

隨著業務的增加,我們服務器需要計算大量的用戶數據,導致用戶跟客服反應頁面不能正常展示。反饋給開發后,我們一看,是服務器異常的錯誤。So,產品想看下我們到底有多少用戶頁面不能正常展示?

方案:

后端人員直接在阿里云后臺去查哪些接口異常 
前端做一個服務器報錯頁,這樣產品在湖人vs爵士季后赛后臺能看到這個頁面的PV,UV

技術方案

因為業務龐大,所以我們不可能區在每個頁面加上重新加載的邏輯。所以初步考慮使用全局重新加載。

需要解決的問題都有哪些?

1、首先我們要有網絡請求失敗的全局控制權(要不然就需要在每個頁面處理失敗的情況) 
2、需要定義好網絡失敗后是如何跳轉到重載頁(R)的(用wx.redirectTo,wx.reLaunch還是其他) 
3、點擊錯誤頁的“重新加載”,如何返回或跳轉到出錯頁(E)(用wx.redirectTo,wx.reLaunch還是其他) 
4、跳轉到出錯頁后,如何重新加載數據(把所有請求都放在Page.onShow()里面?) 
5、那如果從出錯頁的上個界面(P)傳到出錯頁(E)options,那重載頁(R)又將如何處理? 
6、點擊重新加載跟返回,我們希望效果效果一樣,又該如何操作?

實踐的方式如下

1、第一個問題: 比較好解決,我們基于wx.request已經封裝了為fetch(如果還在用wx.request的項目可以考慮封裝下,好處多多)?;趂etch我們可以用res.statusCode來判斷服務器是否出錯。 
2、第二個問題: 暫且先不說具體的跳轉方式是怎樣的,就跳轉的url這個怎么定義也需要我們來討論下。為什么這么說,因為我們的架構涉及到了分包。分包加載意味著我們的代碼不僅僅是在pages下面,還放在了package下。 
基于此,我們在跳轉的時候,url能直接寫成'../serverError/serverError'嗎?在主包下面可以正常跳轉,但是在分包下,路徑是'package/serverError/serverError',這樣跳肯定不行。url應該是根目錄下的路徑,所以'/pages/serverError/serverError'。 
路徑確認后,我們可以跳轉了。如果是wx.redirectTo(關閉當前頁面,跳轉到應用內的某個頁面),想象下關閉E跳轉到R,點擊重新加載,再關閉R跳轉到E,這么跳轉路徑復雜,用戶體驗不好,并且options的參數需要逐級傳遞。wx.reLaunch類似。我們用所以我們選擇wx.navigateTo。 
3、第三個問題: 綜合問題二的解釋,跳回到E,我們用wx.navigateBack。 
4、第四個問題: 如果從R用wx.navigateBack回到E的話,肯定會觸發E.onShow()方法。但是有些請求我們除了寫在Page.onShow()里,還有些是寫在Page.onLoad()里的,所以我們必須想辦法調起E.onLoad()。 
大家對于getCurrentPages()這個方法肯定不陌生,官方定義是來獲取當前頁面棧,我們一般用它來獲取當前頁面路徑。其實在這個過程中,我們是能拿到當前頁面的實例的,并且實例里面有route(頁面路徑)options(頁面傳遞參數)data(頁面初始參數)以及各種function()等等。 
利用previousPageClass()我們可以拿到E的實例,也就可以拿到E.options,當然我們也可以調E.onLoad()。 
util.js

  1. // 獲取當前路徑
  2. function currentPagePath() {
  3. let pageData = getCurrentPages()
  4. if (pageData.length >= 1) {
  5. let len = pageData.length - 1
  6. let data = pageData[len]
  7. return data.route
  8. } else {
  9. return ''
  10. }
  11. }
  12. // 獲取上個界面的實例
  13. function previousPageClass() {
  14. let pageData = getCurrentPages()
  15. if (pageData.length >= 2) {
  16. let len = pageData.length - 2
  17. let preClass = pageData[len]
  18. return preClass
  19. } else {
  20. return ''
  21. }
  22. }
  23. module.exports = {
  24. currentPagePath,
  25. previousPageClass
  26. }

第五個問題: 基于問題的四的方案,我們可以調E.onLoad(E.options)來將我們的參數回傳回去。 
第六個問題: 點擊返回,相當于頁面卸載,也就是執行了R.onUnload(),這個時候我們只需要執行E.onLoad(E.options)這個方法,把options傳過去,以及調用起E.onLoad()就OK了。 
但是點擊重新加載,我們是調的wx.navigateBack(),這個方法也會走R.onUnload()。這是時候可能有些苦惱了,我們隱藏掉返回按鈕?發現官方并沒有提供此方法。禁用R.onUnload(),好像也不行。因為R.onUnload()是在點擊重新加載后才執行的,所以我們可以記錄下用戶是否點擊了重新加載的行為。然后我們通過記錄的行為,即便用戶點擊了重新加載,然后觸發了R.onUnload(),我們不去執行E.onLoad(E.options)就OK了。 
// pages/serverError/serverError.js

  1. import { previousPageClass } from '../../utils/util.js'
  2. let isClickReload = false
  3. Page({
  4. onLoad: function (options) {
  5. isClickReload = false
  6. },
  7. onUnload: function () {
  8. if(!isClickReload) {
  9. this.callbackParams()
  10. }
  11. },
  12. /**
  13. * 點擊事件
  14. */
  15. clickReload: function (e) {
  16. isClickReload = true
  17. wx.navigateBack()
  18. this.callbackParams()
  19. },
  20. // 點擊返回,參數回傳
  21. callbackParams: function () {
  22. let preOptions = previousPageClass().options
  23. previousPageClass().onLoad(preOptions)
  24. }
  25. })

至此所有問題,基本都已解決。 
Demo代碼附上,歡迎參考。

分享至 : QQ空間
收藏
原作者: Luciena 來自: 簡書