navigateBack的用法
wx.navigateBack({
delta: backSize // backsize表示关闭几页,从页面栈中移除几个(包含本页面)
})
项目中的需求
「 需求 」:做一个公共结果页,从其他地方跳转到这个页面,最后点击"完成按钮或者右上角返回"后,回到想回到的页面,并且控制目标页面刷新还是不刷新。
「 分析 」:想实现回到想回到的页面,通过对页面栈的管理来实现。
「 举例 」:页面栈中有1-2-3-4-5,5是公用页面,现在想跳到1,那么就可以通过navigateBack的delta值等于4来控制回到1,我们就动态改变delta的值实现动态跳转,navigateBack会让页面出栈,这样就很好地维护了页面栈。
具体思路
通过getCurrentPages( )能够拿到当前小程序页面栈的数组,数组中有个key为route,该值即是栈里页面地址。要跳转到1,4传值给5,5中通过遍历页面栈数组,判断传过来的值是否等于页面栈中的route值,相等的话,记录index,这样即可完成。
最终效果
无论是触发了ios滑屏退出、android物理按钮返回、小程序左上角返回按钮,都会回到目标页面。
但是,经真机测试后发现。点击左上角返回、手机物理返回键、滑屏返回到目标页面,效果上会关闭两个页面。但最终也可以回到目标页面。只能说功能达到了,效果上没那么完美。这没办法。毕竟页面卸载的处理本身就是一个伪处理-_-
代码说话
这是项目中用到的公用页面,就是通过navigateBack来控制跳转
注释写得很清楚了
想要更清晰地了解页面栈是怎样的,就打断点看一看
有问题欢迎留言讨论😄
Page({
data: {
isInvoke: false,// 是否调用过按钮
isUnload: true,// 是否是卸载的生命周期
resultImg: "", // 图标(页面内使用)
result: {
title: "",// 必传(页面标题)
type: 1,// 必传(0:失败 1:成功)
url: "", // 必传(跳转的url),传空或者不在页面栈中,跳转到首页或指定页面
// 选传(上面文案布局,成功默认是:成功,失败默认:失败)
resultUp: "",
// 选传(下面文案布局,不传默认是空
resultDown: "",
// 选传(按钮名称,成功默认:完成,失败默认:重试)
btnName: "",
// 选传(是否刷新目标页,默认刷新)
isRefresh: true,
}
},
/** 页面初始化 */
onLoad: function (options) {
},
onShow: function () {
this.initData();
},
/** 页面卸载*/
onUnload: function () {
// 如果点击了按钮,就不再调用它
if (!this.data.isInvoke) {
this.data.isUnload = true
this.targetJump()
}
},
/** 初始化值 */
initData: function () {
var result = wx.getStorageSync("result")
if (result) {
// 页面标题
wx.setNavigationBarTitle({
title: result.title
})
var type = result.type
this.data.result.url = result.url
if (typeof (result.isRefresh) != "undefined") {
this.data.result.isRefresh = result.isRefresh
}
if (type) { // 成功
result.btnName = result.btnName ? result.btnName : "完成"
this.data.resultImg = "/resources/success.png"
result.resultUp = result.resultUp ? result.resultUp : "成功"
} else {// 失败
result.btnName = result.btnName ? result.btnName : "重试"
this.data.resultImg = "/resources/failed.png"
result.resultUp = result.resultUp ? result.resultUp : "失败"
}
var btnName = "result.btnName"
var resultUp = "result.resultUp"
var resultDown = "result.resultDown"
this.setData({
resultImg: this.data.resultImg,
[resultUp]: result.resultUp,
[resultDown]: result.resultDown ? result.resultDown : "",
[btnName]: result.btnName
})
}
},
/** 按钮点击事件 */
btnClick: function () {
this.data.isInvoke = true
this.data.isUnload = false
this.targetJump();
},
/** 目标页面跳转 */
targetJump: function () {
// 清除缓存
wx.removeStorageSync("result")
var pages = getCurrentPages()
// 如果url为空或者不在页面栈中,返回首页
var backSize = 100
var target
console.log(pages)
for (var i = 0;i < pages.length;i++) {
if (this.data.result.url.substring(1) == pages[i].route) {
// 自身也在栈中,所以要-1
backSize = pages.length - i - 1;
target = pages[i]
console.log("target", target)
break
}
}
console.log("backSize", backSize)
if (backSize == 100) {// 首页或者指定页面
wx.reLaunch({
url: this.data.result.url,
})
return
}
if (this.data.result.isRefresh) {
// 刷新目标页面
target.onLoad()
}
if (this.data.isUnload) {// 用户点击了返回键
// 如果目标页面在页面栈中倒数第二个位置,返回
if (backSize == 1) {
return
}
// 如果只是调用了小程序返回键,因为back键默认会关掉一页
backSize = backSize - 1
}
wx.navigateBack({
delta: backSize
})
}
})
以上
刚才用苹果滑屏、android点击返回键测试了一下。没有问题,都会走onUnload这个方法。就和我写的那个点击左上角返回是一样的了
然而这样的方式并不完善,用户也会滑屏或者点击原生返回按钮,这样就只能返回到上一页,小程序目前没有提供页面栈的拦截修改功能。
用户滑屏或者点击原生返回,我在页面卸载onUnload中处理了,只要这个页面被卸载了,就能回到目标页面
不会出现页面切换效果上的问题吗?
我用真机测试时发现,点击左上角返回、物理返回、滑屏返回到目标页面,效果上会关闭两个页面。但是最终回到的也是目标页面。只能说功能达到了,效果上没那么完美。这没办法。毕竟页面卸载的处理本身就是一个伪处理。
页面路由规则:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/route.html
onUnload生命周期有很多触发方式,上面的方案可能有问题
我是这样看待的:其实无论它用什么触发方式触发了onUnload,对我这个公共结果页来说,我不用去考虑它,我只要关注如果这个页面被卸载了,那么它就会走onUnload,我就需要跳转到目标页面。所以不太明白了你所指的问题是什么。