小程序页面跳转
微信小程序页面跳转API时需要注意,官方文档中强调:“为了不让用户在使用小程序时造成困扰,我们规定页面路径只能是五层,请尽量避免多层级的交互方式。” 也就是说在连续使用navigateTo进行页面跳转时,若当前页面若正好是第5级,则点击该页面任何绑定触发事件的控件,都不会有任何反应。
更新说明
更新记录:
- 2017 年 9 月,第一版。
- 2017 年 10 月,增加页面跳转流程图及跳转说明。
小程序中页面导航的API
为了避免发生超过五级页面而无法跳转的悲剧,首先要了解清楚小程序中页面导航的API。小程序中页面导航API有五个,两个跳转新页面的API分别为wx.navigateTo和wx.redirectTo,一个用来做重置操作的API为wx.reLaunch,一个用于跳转到tabBar的API为wx.switchTab,还有一个API名为wx.navigateBack,用于返回页面。
wx.navigateBack 在小程序的初始版本中只能回到上一个页面,在最新版本的更新中给 navigateBack 添加了一个参数 delta,用于决定需要返回几层页面,返回的页面数,如果delta大于现有页面数,则返回首页。
几种跳转方式的不同之处
navigator 组件的默认跳转方式与 wx.navigateTo 相同,而如果添加 redirect 属性,则与 wx.redirectTo 的跳转方式相同。
navigateTo 在官方文档中描述如下:
保留当前页面,跳转到应用内的某个页面,使用 wx.navigateBack 可以返回到原页面。
通过 navigateTo 跳转后,可点击左上角的按钮返回上一个页面。而如果多次调用 navigateTo 之后,就需要返回多次才能回到初始页面。因此,官方在此处有一个限制。
注意:为了不让用户在使用小程序时造成困扰,我们规定页面路径只能是五层,请尽量避免多层级的交互方式。
不过上述五层的限制只是针对 navigateTo,redirectTo 则无此限制。因为 redirectTo 的行为是:
关闭当前页面,跳转到应用内的某个页面。
注意: 使用redirectTo跳转到一个之前加载过的页面,不会再次调用该页面的onLoad方法。
通过 redirectTo 跳转后,则无法返回跳转前的页面。但并不是无法调用 navigateBack,而是调用之后,会回到使用 redirectTo 跳转前的上一个页面。
页面栈可以通过 getCurrentPages 方法获取:
getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
上述的「页面路径」可以对应为页面栈中的元素,页面栈中的最后一个元素就是当前显示的页面,页面跳转就是新页面入栈的过程。
上述三种页面 API 的区别在于:
- navigateTo 不会将旧页面出栈;
- redirectTo 会将旧页面出栈,再将需要跳转到的页面入栈;
- navigateBack 则是将页面栈最后一个元素出栈,因此倒数第二个元素会成为最后一个元素,即变成「当前页面」。
结合下面这个例子,如图,
小程序包含 A、B、C、D 四个页面,A 页面为首页。小程序启动后,在 A 页面中,我们通过 navigateTo 跳转到 B 页面,然后在 B 页面中再通过 navigateTo 跳转到 C 页面。
如果通过navigateTo跳转到 D 页面,则在D页面调用navigateBack会返回到C页面;
如果通过redirectTo跳转到 D 页面,则在D页面调用navigateBack会发现不是返回C 页面,而是返回到了 B 页面。
因为调用redirectTo 跳转到 D 页面,redirectTo 会将当前页面出栈,即将 C 页面出栈,再将 D 页面入栈,这时候,页面栈中的元素则会变为 A、B、D。
- navigateTo 不会将旧页面出栈,因此通过 navigateTo 跳转后,页面栈中元素个数会加一,因此在页面栈中元素个数达到 5 之后再调用 navigateTo 会失败,出现无法跳转的错误。
- redirectTo 会在将旧页面出栈后,再将新页面入栈,因此通过 redirectTo 跳转,页面栈中元素个数会保持不变,所以即使在页面栈中元素达到 5 个之后再调用 redirectTo 也能成功跳转。
实际业务流程
业务流程:
点击主页面的“扫码录入”按钮,页面跳转微信扫一扫页面,通过扫描条形码读取商品信息,若扫码到该商品信息存在数据库中,则获取数据库中的信息并将这些商品信息带至至“商品信息”页面,可以在商品信息页面对商品信息进行编辑。编辑结束后,点击商品信息页面底部的保存按钮,保存该条商品的最新信息。
为了在点击页面底部的“保存”按钮后直接跳转至微信扫一扫页面,达到快速扫码录入商品信息的目的。解决方案:
- 直接返回主界面,点击“扫码录入”按钮,跳转至微信扫一扫页面;
- 点击底部“保存”按钮后,立即调用wx.scanCode打开扫一扫页面;
方案1直接被否定了,原因是用户会频繁调用扫一扫进行商品信息的录入。如果在用户录入一天商品信息后,返回到主页面,再一次点击“扫码录入”按钮跳转至扫一扫页面进行商品录入或查询。会使得录入这一操作的连续性被打断,降低录入操作整体流畅度。
方案2在点击保存按钮后直接打开扫一扫固然可以保证操作的连贯性,但此时若在扫一扫页面不做扫码操作,而是点击扫一扫左上角的返回按钮,则返回到上个页面—商品信息保存页面。此时,如果点击“保存”按钮会对商品信息进行重复保存。
那么,能否在微信扫一扫页面做相应处理呢?比如,点击扫一扫左上角的返回按钮时,直接返回到首页。由于扫一扫页面是直接调用wx.scanCode而来的,其并不是以压栈的方式出现在页面控制的层级中。因此,无法通过getCurrentPages()函数获取对应的层级关系。
另外一种方式,针对方案2的问题,需要在点击“商品信息”页的“保存”按钮后做出特别处理,于是在点击保存绑定的事件中设置:
saveTap: function (res) {
wx.request({
url: requestUrl.LookForGoodsUrl
data: {
"userId": userId,
"goodsId": numResult,
"name": name,
"factory": factory,
},
header: {
'content-type': 'application/json'
},
success: function (res) {
if (res.data.code == '0000') {
// 保存成功
wx.redirectTo({
url: '../homePage/homePage'
})
}
}
})
}
将最新商品信息上传至服务器,关闭当前页面,跳转到应用内的某个页面。再调用:
wx.scanCode({
var numResult = res.result;
if (numResult.substring(0, 2) == '69') {
wx.request({
url: requestUrl.LookForGoodsUrl
data: {
"userId": userId,
"goodsId": numResult,
},
header: {
'content-type': 'application/json'
},
success: function (res) {
if (res.data.state == '1') {
// 存在该商品
wx.redirectTo({
url: '../goodsInfo/goodsInfo?goodsChart=' + goodsChart + '&goodsId=' + goodsId,
})
}
}
})
}
})
调用扫一扫,获取商品条码,将获取的条码作为参数上传服务器得到服务器返回的商品信息。再将这些信息传递并跳转至“商品信息”页,展示这些信息。再次扫描商品条码时,重复以上操作。
但是为了在商品信息页面点击“保存”按钮时关闭当前页面,使用了wx.redirectTo,会先返回到首页(homePage),然后再调出扫一扫页面。这期间会出现短暂(大概2~3秒钟)的停顿,停顿期间页面(homePage)仍然可以操作,会误触页面上的其他点击事件。最后,即使在该页面(homePage)加上loading,以防止误触。仍然无法回避短暂停顿后再跳转扫一扫页面的问题。
最后的解决方案是: 点击商品信息页的“保存”按钮后,将该按钮隐藏。这样当从扫一扫页面返回商品信息页时就不会出现重复保存数据的问题了。
–EOF–
若无特别说明,本站文章均为原创,转载请保留链接,谢谢