《微信小程序七日谈》- 第四天:页面路径最多五层?导航能够这么玩

《微信小程序七日谈》系列文章:javascript

  1. 第一天:人生若只如初见
  2. 次日:你可能要抛弃原来的响应式开发思惟
  3. 第三天:玩转Page组件的生命周期
  4. 第四天:页面路径最多五层?导航能够这么玩
  5. 第五天:你可能要在登陆功能上花费大力气
  6. 第六天:小程序devtool隐藏的秘密;
  7. 第七天:不要捡了芝麻丢了西瓜

本系列的文章并不是初学教程,而是笔者在具体开发过程当中遇到的问题以及部分解决方案。html

微信小程序提供导航相关的APIjava

  • 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组件,经过子路由控制模板的渲染,之因此这样作有如下几点考虑:

  1. 两个实体页面之间有不少共用的数据;
  2. 58到家的小程序是复用了现存的部分接口,两个页面之间的数据是混合在一块儿的,融合也是为了不接口的重构;

既然融合为一个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子路由。这个逻辑中须要注意的是:

  • 第四层页面跳转第五层页面是隐藏(Hide)而不是卸载(Unload);
  • 第五层页面返回第四层页面后会触发第四层页面的onShow钩子函数。

也就是说,咱们能够再onShow钩子函数中进行路由的分发。可是如何获取路由字段呢?你们可能想到的第一个方案就是经过url传参,惋惜这个方案是行不通的。首先,微信小程序官方文档中关于Page组件钩子函数的说明,只有onLoad函数能够获取由url query传递的数据,其他的任何钩子函数都不能获取;其次,第五层页面的提交行为返回第四层页面是由wx.navigateBack()API实现的,这个API的功能是返回页面栈中的上一层页面,并不支持指定的修改url,因此url传参这条路是走不通的。

那么使用cookie是否可行呢?虽然微信小程序不支持cookie,但cookie的理念能够提供给咱们解决问题的思路:将数据先储存在本地,跳转页面后获取本地数据进行相应处理。

有了思路,天然而然地便想到相似cookie的本地storage

使用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层的页面路径,在这种状况下,咱们不得不牺牲必定的用户体验,以保证功能的完整。本文提到的方案是与业务场景息息相关的,只是一家之言,并不是最佳实践。但愿可以给你们一点参考。

相关文章
相关标签/搜索