小程式無限層級路由方案

大轉轉FE發表於2018-09-19

小程式原生頁面存在層級限制,超過一定層數就會無法開啟新頁面。一開始這個限制為不超過5層,目前是不超過10層。

這個限制對於體量較大的小程式來說,挺難受的。特別是只能開啟5層那會兒,業務流程很容易一不小心就超了,比如:首頁-搜尋結果頁-商品詳情頁-聊天頁-下單頁-地址選擇頁-...;更有訪問迴路防不勝防,比如:商品詳情頁-檢視更多頁-商品詳情頁-檢視更多頁-...、商品詳情頁-聊天頁-個人主頁-商品詳情頁-聊天頁-個人主頁-商品詳情頁-...、諸如此類。即使後來放寬至了10層,還是很容易遭遇層級溢位。

一種處理思路是調整互動路徑,嚴格控制層級數量。但是這種處理方案,一則很多時候會犧牲使用者體驗,比如為避免個人主頁和商品詳情頁的訪問迴路,要麼不能在個人主頁中訪問使用者商品,要麼不能在商品詳情頁中訪問賣家主頁,要麼訪問時需要替換當前不能返回繼續瀏覽,不管怎麼取捨都會犧牲某些使用者的瀏覽訴求;二則維護成本特別高,業務邏輯越來越複雜,互動路徑越來越發散,路徑的統一梳理和規劃就會越來越困難,而且管理過程對業務不透明,業務方在設計需求時要受到互動路徑的種種限制,甚至一個需求的互動調整很可能無意中造成另一個需求層級溢位,維護成本高且不斷膨脹。

因而本文考慮並實現了另一種處理思路:在小程式中支援不限層級的路由過程。

策略

  • 修改小程式預設導航行為,自行維護完整歷史記錄
  • 頁面層級小於等於10時,導航行為與原生導航行為一致
  • 請求開啟第11層及以上時,邏輯層級記錄完整歷史,實際層級每次都是直接將第10層替換為目標頁面
  • 返回時,邏輯層級相應回退;若回退後邏輯層級大於等於10,則實際層級將第10層替換為目標頁面,否則實際層級回退到相應頁面
  • demo:
  邏輯層級 1 - 2 - ... - 8 - 9 - 10
  實際層級 1 - 2 - ... - 8 - 9 - 10
  
  開啟
  
  邏輯層級 1 - 2 - ... - 8 - 9 - 10 - 11
  實際層級 1 - 2 - ... - 8 - 9 - 11
  
  開啟,開啟,開啟
  
  邏輯層級 1 - 2 - ... - 8 - 9 - 10 - 11 - 12 - 13 - 14
  實際層級 1 - 2 - ... - 8 - 9 - 14
  
  返回
  
  邏輯層級 1 - 2 - ... - 8 - 9 - 10 - 11 - 12 - 13
  實際層級 1 - 2 - ... - 8 - 9 - 13
  
  返回,返回,返回
  
  邏輯層級 1 - 2 - ... - 8 - 9 - 10
  實際層級 1 - 2 - ... - 8 - 9 - 10
  
  返回
  
  邏輯層級 1 - 2 - ... - 8 - 9
  實際層級 1 - 2 - ... - 8 - 9
複製程式碼

實現

轉轉 實現了上述策略,並提供開源使用,地址:github.com/zhuanzhuanf…,歡迎使用或參閱。

主要難點及實現方案:

  • 如何接管路由過程
    • 要求所有頁面不使用<navigator>元素,統一使用js觸發跳轉
    • 要求所有頁面不直接呼叫wx.navigateTo、wx.redirectTo等路由相關介面,統一改用模組封裝的相應介面
  • 如何監聽返回行為
    • 統一監聽頁面的onUnload函式,結合路由過程判斷是否使用者返回
  • 如何相容系統互動
    • 問題:系統互動會跳出正常路由流程,並且難以接管或監控,如:使用者點選右上角返回主頁按鈕、使用者切後臺後又從其它入口進入、使用者強制關閉小程式程式等
    • 處理:引入校正機制,在合適的時機根據系統路由棧對自行維護的路由棧進行校正。這樣可以保證10層以內路由正確性。系統互動多是回到第1層,會被成功校正。
  • 如何避免/相容程式碼疏漏
    • 問題:接管&監聽過程要求所有頁面遵循一些編碼約束,如何保證這些約束切實全面生效;萬一有頁面未遵循約束,能否依然保證健壯性
    • 處理1:編寫並配置相應eslint規則,保證約束被切實遵循
    • 處理2:上一條中的校正機制,保證即使有程式碼疏漏,在10層內也會被校正;10層外可能會影響返回邏輯正確性,但一般不會造成頁面功能問題。
  • 如何進行狀態恢復
    • 問題:返回後邏輯層級大於等於10時,實際是在第10層重新載入目標頁面;使用者在前一頁面的表單輸入等狀態資訊並不會像系統返回一樣正常保留
    • 處理:在合適的時機儲存頁面的data,返回時予以恢復

成本

  • 接入成本
    • 需要引入並配置路由模組
    • 需要檢查並修改專案中所有頁面跳轉過程,統一使用模組封裝的介面
    • 需要統一監聽所有頁面的onUnload函式
  • 維護成本
    • 新增頁面跳轉過程,需統一使用模組封裝的介面
    • 新增頁面onUnload函式需接入統一監聽
  • 效能成本
    • 模組執行邏輯相對簡單,記憶體開銷相對較小,頁面效能暫未發現明顯損耗

收益

  • 無限層級
    • 避免複雜/迴圈訪問導致頁面無法開啟
    • 可以放心地向使用者提供適合的訪問入口,不必過分擔心路徑限制
  • 完全的路由管控能力
    • 可以完全監控路由過程並實現或引入一些附加功能
    • 附加功能:例項覆蓋自動恢復
      • 問題:wepy框架存在單例項問題,同一路徑頁面被開啟兩次時,其資料會相互影響,如:詳情頁A - 詳情頁B - 返回A,點選檢視大圖 - B的圖片(而不是A的圖片) 詳見issue:兩級頁面為同一路由時,後者資料覆蓋前者
      • 策略:返回時,若判斷目標頁面資料已被覆蓋,則自動予以恢復
      • 引入:參見模組使用說明
    • 附加功能: 免併發
      • 問題:使用者連續快速點選多個/多次按鈕時,會一次性開啟多個視窗,一則造成層級膨脹,二則影響瀏覽體驗
      • 策略:第一次點選造成的跳轉完成之前無視後續點選產生的跳轉請求
      • 引入:參見模組使用說明
    • 附加功能:資料預先載入
      • 問題:小程式的page1跳轉到page2,到page2的onLoad是存在一個300ms ~ 400ms的延時的,在page2的onLoad中才開始獲取資料會浪費這個延時
      • 策略:在 page1 中預先拿取資料,然後在 page2 中直接使用資料;wepy框架對此有良好的實現,參見WePY 在小程式效能調優上做出的探究
      • 引入:參見模組使用說明

效果

無限層級路由方案已在 轉轉二手交易網 小程式中應用了很長一段時間,歡迎體驗:
微信-我-錢包-轉轉二手

無限層級路由方案已被抽離封裝成獨立開源模組,歡迎直接使用:github.com/zhuanzhuanf…

相關文章