《微信小程序七日談》系列文章:javascript
本系列的文章並不是初學教程,而是筆者在具體開發過程當中遇到的問題以及部分解決方案。html
微信小程序提供導航相關的API:java
wx.navigateTo()
;wx.redirectTo()
;wx.navigateBack()
。使用wx.navigateTo()
或者<navigator>
組件跳轉的頁面路徑最多隻有5層,這些頁面路徑是能夠經過wx.navigateBack()
API或者左上角返回按鈕按順序返回的。當頁面路徑大於5層時,使用wx.navigateTo()
進行下一頁嗎跳轉會拋出錯誤:web
navigateTo:fail webview count limit exceed.
可是某些業務場景存在多頁面互動的交互邏輯,遠遠不止5層頁面棧。好比筆者近期參與開發的58到家小程序中存在以下的業務場景:
一、用戶進入小程序,展現首頁;
二、首頁存在一個以下圖的底部導航欄:
小程序
用戶點擊「個人」進入我的中心,此時頁面棧爲首頁->我的中心,共2層。
三、我的中心頁面存在「個人收入」入口,以下:
微信小程序
四、用戶從我的中心進入個人收入頁面,此時頁面棧爲首頁->我的中心->個人收入,共3層;
五、個人收入頁面提供「提現」頁面的入口,以下:
api
六、用戶進入提現頁面,此時的頁面棧爲首頁->我的中心->個人收入->提現,共4層。此時留給咱們可支配的頁面棧只剩下一層了。提現流程以下:
微信
提現流程存在多頁面直接的數據共享和交互,若是是常規的webapp,咱們一般會考慮使用hash路由或者乾脆作成獨立的幾個頁面使用url傳參進行數據通訊。可是進入提現頁面以後,咱們最多隻能再添加一個獨立頁面了。也就是說,銀行列表頁、綁定銀行卡頁和提交成功頁三者只能再使用一個頁面棧(並不是一個頁面)承載。如何用僅剩的最後一層頁面棧實現上述複雜的提現流程呢?cookie
首先第一步是將提現行爲細分,由於只能再添加一個獨立頁面,因此須要合併一些可在一個頁面完成的行爲。上文的流程圖其實遺漏了一個行爲:綁定銀行卡頁面點擊銀行卡須要顯示銀行列表頁。也就是容許用戶從新選擇銀行。因此其實總體的提現流程以下:
app
小程序標題欄左上角返回按鈕的行爲(圖中標紅的線條)是返回頁面棧的上一頁面,代碼是沒法干預的。
整個流程中必須支持「返回」按鈕正常返回上一頁面的行爲有:
要保證第二條「提現頁面進入的銀行列表頁面,正常返回提現頁面」,就必須將銀行列表頁獨立爲一個頁面。至此,最後一層頁面棧就定型了。那麼剩下的綁定銀行卡和提交成功頁面怎麼辦呢?
須要注意的是,銀行列表頁面與綁定銀行卡頁面之間有一個雙向的交互行爲,因爲最後一個獨立頁面已經肯定爲銀行列表頁了,因此不得不從中犧牲必定的用戶體驗:綁定銀行卡頁面跳轉到銀行列表頁後不能正常返回。有了這個前提,咱們能夠把銀行列表和綁定銀行卡兩個邏輯頁面合併爲一個實體頁面,經過子路由控制行爲展現。
再次回顧上文的交互流程圖還能夠獲得另一個信息:提交成功頁面的返回邏輯與提現頁面徹底相同。因此,二者一樣能夠合併爲一個實體頁面,由子路由控制行爲展現。
以第二步的合併規則爲準,實體頁面的交互流程以下:
data.route
實現子路由微信小程序的Page是沒有子路由概念的,咱們在此討論的子路由其實就是根據Page組件的某個data字段進行不一樣模板的分發渲染。
首先定義支持的子路由列表:
// 路由列表 const ROUTES = { index: 'index', banklist: 'banklist', setcard: 'setcard', done: 'done' };
咱們在代碼上又進一步的融合,將第四層頁面和第五層頁面兩個實體頁面融合爲同一個Page組件,經過子路由控制模板的渲染,之因此這樣作有如下幾點考慮:
既然融合爲一個Page組件,那麼如何實現頁面的跳轉呢?其實很簡單,使用wx.navigateTo()
API以下:
wx.navigateTo({ url: './index?route=' + ROUTES.banklist });
上述代碼實現了跳轉到同一Page組件的功能,而且跳轉的頁面會被加入到頁面棧中。
而後在index.wxml
中增長路由數據的邏輯判斷分發:
<block wx:if="{{route=='index'}}"> <include src="_part/basic/index.wxml"/> </block> <block wx:if="{{route=='banklist'}}"> <include src="_part/banklist/index.wxml"/> </block> <block wx:if="{{route=='setcard'}}"> <include src="_part/setcard/index.wxml"/> </block> <block wx:if="{{route=='done'}}"> <include src="_part/done/index.wxml"/> </block>
前置頁面進入第四層頁面時默認的是index
子路由頁面,有第五層頁面的綁定銀行卡提交後返回第四層頁面時顯示done
子路由。這個邏輯中須要注意的是:
onShow
鉤子函數。也就是說,咱們能夠再onShow
鉤子函數中進行路由的分發。可是如何獲取路由字段呢?你們可能想到的第一個方案就是經過url傳參,惋惜這個方案是行不通的。首先,微信小程序官方文檔中關於Page組件鉤子函數的說明,只有onLoad
函數能夠獲取由url query傳遞的數據,其他的任何鉤子函數都不能獲取;其次,第五層頁面的提交行爲返回第四層頁面是由wx.navigateBack()
API實現的,這個API的功能是返回頁面棧中的上一層頁面,並不支持指定的修改url,因此url傳參這條路是走不通的。
那麼使用cookie是否可行呢?雖然微信小程序不支持cookie,但cookie的理念能夠提供給咱們解決問題的思路:將數據先儲存在本地,跳轉頁面後獲取本地數據進行相應處理。
有了思路,天然而然地便想到相似cookie的本地storage。
第一步:點擊第五層頁面的提交按鈕後,首先在storage中儲存第四層頁面的route值:
wx.setStorage({ key: 'dj_deposits_route', data: ROUTES.done });
第二步:在第四層頁面的onShow
函數內獲取storage中的route數據並賦值給data中的route字段,模板便會同步刷新:
let _route = wx.getStorageSync('dj_deposits_route'); this.setData({ route: _route });
微信小程序的頁面路徑限制爲最多5層,多於5層的頁面將不會跳轉而且會拋出錯誤信息。而咱們產品的某些業務場景不止存在5層的頁面路徑,在這種狀況下,咱們不得不犧牲必定的用戶體驗,以保證功能的完整。本文提到的方案是與業務場景息息相關的,只是一家之言,並不是最佳實踐。但願可以給你們一點參考。