评论

小程序之「 navigateBack 」公共页面案例

如何通过navigateBack管理页面栈? 指哪打哪才是navigateBack正确使用姿势!

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
    })
  }
})

以上

最后一次编辑于  2019-05-28  
点赞 1
收藏
评论

3 个评论

  • a.Yo^Long
    a.Yo^Long
    2019-05-24

    刚才用苹果滑屏、android点击返回键测试了一下。没有问题,都会走onUnload这个方法。就和我写的那个点击左上角返回是一样的了

    2019-05-24
    赞同 1
    回复
  • 长天
    长天
    2019-05-24

    然而这样的方式并不完善,用户也会滑屏或者点击原生返回按钮,这样就只能返回到上一页,小程序目前没有提供页面栈的拦截修改功能。

    2019-05-24
    赞同 1
    回复 3
    • a.Yo^Long
      a.Yo^Long
      2019-05-24

      用户滑屏或者点击原生返回,我在页面卸载onUnload中处理了,只要这个页面被卸载了,就能回到目标页面

      2019-05-24
      1
      回复
    • 长天
      长天
      2019-05-27回复a.Yo^Long

      不会出现页面切换效果上的问题吗?

      2019-05-27
      回复
    • a.Yo^Long
      a.Yo^Long
      2019-05-28回复长天

      我用真机测试时发现,点击左上角返回、物理返回、滑屏返回到目标页面,效果上会关闭两个页面。但是最终回到的也是目标页面。只能说功能达到了,效果上没那么完美。这没办法。毕竟页面卸载的处理本身就是一个伪处理。

      2019-05-28
      回复
  • 子非鱼
    子非鱼
    2019-05-28

    页面路由规则:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/route.html

    onUnload生命周期有很多触发方式,上面的方案可能有问题


    2019-05-28
    赞同
    回复 1
    • a.Yo^Long
      a.Yo^Long
      2019-05-28

      我是这样看待的:其实无论它用什么触发方式触发了onUnload,对我这个公共结果页来说,我不用去考虑它,我只要关注如果这个页面被卸载了,那么它就会走onUnload,我就需要跳转到目标页面。所以不太明白了你所指的问题是什么。

      2019-05-28
      回复
登录 后发表内容