作者:leejimqiu 丘利俊
編輯:edwinzeng 曾鑫鵬
微信官方提供了基礎的路由能力,在日常的開發中雖已夠用,但随着開發的深入,會遇到許多值得思考提煉的問題。本文将探讨作者在微信小程式(以下簡稱小程式)開發當中遇到的問題,以及解決方案設計。
參考“WHY-HOW-WHAT"黃金圈思維法則,首先講述為什麼小程式的路由需要封裝設計,也就是存在哪些問題需要封裝處理?
1
存在的問題
路由跳轉的路徑與檔案路徑耦合
小程式的路由跳轉使用的是真實檔案路徑,是以若檔案的結構發生變化,必會影響到所有的頁面的跳轉路徑。
筆者在實際開發中就遇到這個問題,以小程式分包舉例。
小程式的分包是以檔案夾為機關的。如果要将一系列的頁面拆分成分包,則需要将這些檔案移至同個目錄之下,是以必然導緻路由的跳轉路徑發生變更。如果此時路由跳轉均是直接通過檔案路徑跳轉的話,則需要全局改動,導緻的工作量不少。
另外,當開發團隊比較龐大時,不同的業務之間總會存在互相跳轉的情況。當其中一個頁面位址發生變更時,其他業務跳轉到該頁面的路徑都需要手動變更。若此時通知不及時,或者遺漏了一些地方,導緻跳轉失敗,終會釀成大錯。
路由傳參
目前小程式支援的傳參方式,即通過跳轉路徑上的query查詢參數。
通過query傳參的問題,與在Web上URL傳參是一緻的,比如:
- query的參數長度有限
- query隻能傳遞可序列化的資料
- 導航前需手動序列化,到達目标頁面後需反序列化
條件導航
在日常業務中,會存在一些頁面需要一定條件才允許進入的。
舉個例子,會員服務是一種很常見的能力,而會員中心的進入條件是:
- 該使用者已經完成登入
- 該使用者是本産品的會員
一般情況下,這種有特定準入資格的頁面的導航邏輯是這樣的:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SNyEGZiZGM1UGZjJDO5MWOhRjZxI2Y2QmZkJjN2MGO58CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
這種方式簡單明了,但存在一個問題:需要每次跳轉前主動判斷,邏輯備援以外,還可能被遺漏。
2
思路
小程式本身已提供了基礎的路由導航能力,不像react、vue.js那樣需要從底層進行封裝,進而提供路由能力。但是,本質上小程式可以了解成類vue.js這樣的架構,是以可以從vue.js的路由庫vue-router上找到靈感,進而解決以上問題。
命名路由
使用命名路由的方式可以解決前文提及的跳轉路徑和檔案真實路徑耦合問題。
通過Map來映射頁面ID和頁面位址,路由跳轉時,僅能使用頁面ID進行路由跳轉。
下面以導航至首頁舉例:
由于小程式有tab頁面和普通頁面之分,是以導航至tab頁時需使用switchTab
細心的讀者可能會發現上文使用了go方法,而不是switchTab。其實,具體哪些頁面屬于tab頁面,在app.json已經明确配置。對于使用者來說,不需要關心跳轉的頁面是屬于哪種類型,這些細節都應該統一在底層封裝好。下面羅列Router與官方API的對應關系:
Router API的設計原則是保持簡單,以及盡量保持與web規範一緻
傳遞參數
微信官方提供的query方式傳參,若參數是普通資料類型(如Number、String)時可以直接使用;但若是涉及到複雜資料類型(如Array、Object)時,需要先做序列化處理,當資料較為龐大時,性能的損耗還是比較明顯的。
是以,在記憶體上傳遞參數是比較便利且容易想到的辦法。
利用資料字典,将頁面ID作為key、傳遞的參數作為value,寫入Router的state:
在目标頁面上,可以通過router.getParams()方法,擷取傳遞的參數。
由于采用了命名路由的方式,可以使用頁面ID作為key,避免了使用跳轉路徑做key時,涉及到的絕對與相對路徑問題。
條件導航
條件導航可以使用類似vue-router的導航守衛來解決問題。
由于路由的能力是微信官方提供的,是以無法像 vue-router 那樣提供多類型的導航守衛,但僅有全局導航守衛也足夠使用。
以下仍以“會員中心”的進入邏輯舉例,并簡要介紹實作思路:
其中,to和from目前是pageID,其實可以封裝更多資訊,以保證導航守衛可以盡可能擁有更多的資訊。是以to可以了解成是即将進入的頁面路由對象,而from則是目前正要離開的路由對象。路由對象可以包含以下資訊:
- ID:頁面ID
- path:頁面ID對應的path
- params:傳遞的參數
- query: URL的查詢參數
配置資訊
由前文提到的 命名路由 做法需要一個配置檔案來關聯頁面ID與頁面路徑的關系。頁面的配置資訊,則是使用router.config.js設定,然後通過建構工具編譯轉成app.json。以下是route.config.js:
其中,跳轉首頁則是router.go('home');而跳轉分包health的首頁則是使用router.go('health.home')
通過以上的配置檔案,使用建構工具轉換成微信官方可識别的app.json配置:
輔助函數
在日常開發當中,經常會用到一些和路由相關的通用輔助函數,如擷取目前頁面,擷取上個頁面等。這些輔助函數都應該統一抽象封裝,避免代碼備援。
navigator元件
微信官方除了提供API用于導航以外,還提供了navigator元件。
另外還有functional-page-navigator是用于插件當中,不能在小程式包使用,是以本文暫且将其忽略。
由于navigator的跳轉參數仍是使用path,是以筆者将其進行二次封裝,改造成可以通過pageID跳轉:
3
總結
由于小程式相對比較封閉,是以在路由上能做的東西比較有限。
但路由又與許多概念有千絲萬縷的關系。比如路由與檔案結構關聯,而檔案結構又影響到分包的設計,環環相扣,影響到的地方則會越來越多。
是以,能提前看到本文提到的可能出現的問題,也許對後續的小程式開發有一定的參考意義。
另外,前文提到的很多問題,在早期開發,或者沒有深入開發之前,都不會遇到。但是當你開始經曆前文提到的那些問題時,往往此時的改造成本已經很大了。是以希望本文能給你帶了一些啟發,在早期規避這些問題,那本文的使命就達到了。