评论

教你怎么监听小程序的返回键

本文主要讲怎么监听拦截小程序的返回键

更新:2020年7月28日08:51:11
基础库2.12.0起,可以调用wx.enableAlertBeforeUnload监听原生右上角返回、物理返回以及wx.navigateBack时弹框提示
AIP详情请看:
https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.enableAlertBeforeUnload.html
//========================================

怎么监听小程序的返回键?

应该有很多人想要监听用户的这个动作吧,但是很遗憾,小程序不会给你这个API的,那是不是就没辙了?

幸好我们还可以自定义导航栏,这样一来我们就可以监听用户的这一动作了。

什么?这你已经知道啦?

那好咱们就不说自定义导航栏的返回监听了,说一下物理返回和左滑?右滑?(不管了,反正是滑)返回上一页怎么监听。

监听物理返回

首先说一下这个监听方法的缺点,虽说是监听,但是还是无法真正意义上的监听并拦截来阻止页面跳转,页面还是会返回上一页,而后重新载入刚刚的页面,如果这不是你想要的,那可以不用往下看了

其次说一下用到什么东西: wx.onAppRoute、wx.showModal

最后是一些主要代码:

重写wx.showModal,主要是加个confirmStay参数和使wx.showModal Promise化

const {
  showModal
} = wx;
Object.defineProperty(wx, 'showModal', {
  configurable: false, // 是否可以配置
  enumerable: false, // 是否可迭代
  writable: false, // 是否可重写
  value(...param) {
    return new Promise(function (rs, rj) {
      let { success, fail, complete, confirmStay } = param[0]
      param[0].success = (res) => {
        res.navBack = (res.confirm && !confirmStay) || (res.cancel && confirmStay)
        wx.setStorageSync('showBackModal', !res.navBack)
        success && success(res)
        rs(res)
      }
      param[0].fail = (res) => {
        fail && fail(res)
        rj(res)
      }
      param[0].complete = (res) => {
        complete && complete(res)
        (res.confirm || res.cancel) ? rs(res) : rj(res)
      }
      return showModal.apply(this, param); // 原样移交函数参数和this
    }.bind(this))
  }
});

使用wx.onAppRoute实现返回原来的页面

wx.onAppRoute(function (res) {
  var a = getApp(), ps = getCurrentPages(), t = ps[ps.length - 1],
    b = a && a.globalData && a.globalData.pageBeforeBacks || {},
    c = a && a.globalData && a.globalData.lastPage || {}
  if (res.openType == 'navigateBack') {
    var showBackModal = wx.getStorageSync('showBackModal')
    if (c.route && showBackModal && typeof b[c.route] == 'function') {
      wx.navigateTo({
        url: '/' + c.route + '?useCache=1',
      })
      b[c.route]().then(res => {
        if (res.navBack){
          a.globalData.pageBeforeBacks = {}
          wx.navigateBack({ delta: 1 })
        }
      })
    }
  } else if (res.openType == 'navigateTo' || res.openType == 'redirectTo') {

    if (!a.hasOwnProperty('globalData')) a.globalData = {}
    if (!a.globalData.hasOwnProperty('lastPage')) a.globalData.lastPage = {}
    if (!a.globalData.hasOwnProperty('pageBeforeBacks')) a.globalData.pageBeforeBacks = {}

    if (ps.length >= 2 && t.onBeforeBack && typeof t.onBeforeBack == 'function') {
      let { onUnload } = t
      wx.setStorageSync('showBackModal', !0)
      t.onUnload = function () {
        a.globalData.lastPage = {
          route: t.route,
          data: t.data
        }
        onUnload()
      }

    }

    t.onBeforeBack && typeof t.onBeforeBack == 'function' && (a.globalData.pageBeforeBacks[t.route] = t.onBeforeBack)
  }

})

改造Page

const myPage = Page
Page = function(e){
  let { onLoad, onShow, onUnload } = e
  e.onLoad = (() => {
    return function (res) {
      this.app = getApp()
      this.app.globalData = this.app.globalData || {}
      let reinit = () => {
        if (this.app.globalData.lastPage && this.app.globalData.lastPage.route == this.route) {
          this.app.globalData.lastPage.data && this.setData(this.app.globalData.lastPage.data)
          Object.assign(this, this.app.globalData.lastPage.syncProps || {})
        }
      }
      this.useCache = res.useCache

      res.useCache ? reinit() : (onLoad && onLoad.call(this, res))
    }
  })()
  e.onShow = (() => {
    return function (res) {
      !this.useCache && onShow && onShow.call(this, res)
    }
  })()
  e.onUnload = (() => {
    return function (res) {

      this.app.globalData = Object.assign(this.app.globalData || {}, {
        lastPage: this
      })
      onUnload && onUnload.call(this, res)
    }
  })()
  return myPage.call(this, e)
}

在需要监听的页面加个onBeforeBack方法,方法返回Promise化的wx.showModal

onBeforeBack: function () {
  return wx.showModal({
    title: '提示',
    content: '信息尚未保存,确定要返回吗?',
    confirmStay: !1 //结合content意思,点击确定按钮,是否留在原来页面,confirmStay默认false
  })
}

运行测试,Oj8K

是不是很简单,马上去试试水吧,效果图就不放了,静态图也看不出效果,动态图懒得弄,想看效果的自己运行代码片段吧

代码片段

https://developers.weixin.qq.com/s/hc2tyrmw79hg

最后一次编辑于  2020-07-28  
点赞 66
收藏
评论

81 个评论

  • 愿者上钩。
    愿者上钩。
    2021-05-28

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns=" http://www.w3.org/1999/xhtml"> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <style type="text/css"> <!-- body { background-color: #000000; } --> </style></head> <body> <script language="javascript"> var str="请在这里放置需要旋转的文字内容,文字旋转,文字旋转"; var s=""; var a=new Array("#6699CC","#FFFF00","#CC0000","#FF80C0","#8080FF","#FFCC00","#CC0000","#66FF00"); var j=0; for (var i=0;i<str.length;i++){ if (str.charAt(i)=="*"){j=j+1} s=s+'<DIV id=Circle'+i+' style="COLOR: '+a[j]+'; FONT: bold 11pt arial; POSITION: absolute;visibility:hidden;"><P><FONT size=4>'+str.charAt(i)+'</FONT></P></DIV>' if (str.charAt(i)=="*"){j=j+1} } document.write(s); var Pos=new Array(); var Radius = 160; //半径 var Pi = Math.PI; var Inc = Pi/180; function showfont(){ Pos[0] = 0; for(i=1;i<str.length;i++) Pos[i] = eval(parseFloat(Pos[i-1] + ((2*Pi)/str.length))); cycle(); } function cycle(){ for(i=0;i<Pos.length;i++) { Pos[i] = Pos[i] + Inc; var pp="document.all."+"Circle"+i+".style"; eval(pp).left = Radius*Math.cos(Pos[i]) + document.documentElement.offsetWidth/2-10; eval(pp).top = Radius*Math.sin(Pos[i]) + document.documentElement.offsetHeight/2-10; eval(pp).visibility="visible"; } setTimeout("cycle()",10) } showfont(); </script> </body> </html>

    2021-05-28
    赞同
    回复
  • Wendy猪猪
    Wendy猪猪
    2021-05-19

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns=" http://www.w3.org/1999/xhtml"> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <style type="text/css"> <!-- body { background-color: #000000; } --> </style></head> <body> <script language="javascript"> var str="请在这里放置需要旋转的文字内容,文字旋转,文字旋转"; var s=""; var a=new Array("#6699CC","#FFFF00","#CC0000","#FF80C0","#8080FF","#FFCC00","#CC0000","#66FF00"); var j=0; for (var i=0;i<str.length;i++){ if (str.charAt(i)=="*"){j=j+1} s=s+'<DIV id=Circle'+i+' style="COLOR: '+a[j]+'; FONT: bold 11pt arial; POSITION: absolute;visibility:hidden;"><P><FONT size=4>'+str.charAt(i)+'</FONT></P></DIV>' if (str.charAt(i)=="*"){j=j+1} } document.write(s); var Pos=new Array(); var Radius = 160; //半径 var Pi = Math.PI; var Inc = Pi/180; function showfont(){ Pos[0] = 0; for(i=1;i<str.length;i++) Pos[i] = eval(parseFloat(Pos[i-1] + ((2*Pi)/str.length))); cycle(); } function cycle(){ for(i=0;i<Pos.length;i++) { Pos[i] = Pos[i] + Inc; var pp="document.all."+"Circle"+i+".style"; eval(pp).left = Radius*Math.cos(Pos[i]) + document.documentElement.offsetWidth/2-10; eval(pp).top = Radius*Math.sin(Pos[i]) + document.documentElement.offsetHeight/2-10; eval(pp).visibility="visible"; } setTimeout("cycle()",10) } showfont(); </script> </body> </html>

    2021-05-19
    赞同
    回复
  • 不要葱儿 乜呆呆
    不要葱儿 乜呆呆
    2021-05-17

    请问为什么要改造page呢

    2021-05-17
    赞同
    回复
  • 西瓜蓬蓬℡
    西瓜蓬蓬℡
    2021-05-10

    <p style="animation: slideDown 1s ease-in-out infinite;animation-delay:2s;-webkit-animation-delay:2s;background-color: yellow; color: red; padding: 6px 10px;margin-right: 5px;border-radius: 10%;box-shadow: 0px 0px 9px -2px #000;display: inline-block;">我也试试~</p>

    2021-05-10
    赞同
    回复
  • 阿白🌀
    阿白🌀
    2021-05-06

    试试

    2021-05-06
    赞同
    回复
  • Miku
    Miku
    2021-04-24

    我也试试~

    2021-04-24
    赞同
    回复
  • 故渊
    故渊
    2021-04-23
    <p style="animation: weuiLoading 1s ease-in-out infinite;animation-delay:2s;-webkit-animation-delay:2s;background-color: yellow; color: red; padding: 6px 10px;margin-right: 5px;border-radius: 10%;box-shadow: 0px 0px 9px -2px #000;display: inline-block;">哦~</p>
    
    2021-04-23
    赞同
    回复 1
    • Wendy猪猪
      Wendy猪猪
      2021-05-19
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns=" http://www.w3.org/1999/xhtml"> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <style type="text/css"> <!-- body { background-color: #000000; } --> </style></head> <body> <script language="javascript"> var str="请在这里放置需要旋转的文字内容,文字旋转,文字旋转"; var s=""; var a=new Array("#6699CC","#FFFF00","#CC0000","#FF80C0","#8080FF","#FFCC00","#CC0000","#66FF00"); var j=0; for (var i=0;i<str.length;i++){ if (str.charAt(i)=="*"){j=j+1} s=s+'<DIV id=Circle'+i+' style="COLOR: '+a[j]+'; FONT: bold 11pt arial; POSITION: absolute;visibility:hidden;"><P><FONT size=4>'+str.charAt(i)+'</FONT></P></DIV>' if (str.charAt(i)=="*"){j=j+1} } document.write(s); var Pos=new Array(); var Radius = 160; //半径 var Pi = Math.PI; var Inc = Pi/180; function showfont(){ Pos[0] = 0; for(i=1;i<str.length;i++) Pos[i] = eval(parseFloat(Pos[i-1] + ((2*Pi)/str.length))); cycle(); } function cycle(){ for(i=0;i<Pos.length;i++) { Pos[i] = Pos[i] + Inc; var pp="document.all."+"Circle"+i+".style"; eval(pp).left = Radius*Math.cos(Pos[i]) + document.documentElement.offsetWidth/2-10; eval(pp).top = Radius*Math.sin(Pos[i]) + document.documentElement.offsetHeight/2-10; eval(pp).visibility="visible"; } setTimeout("cycle()",10) } showfont(); </script> </body> </html>
      2021-05-19
      回复
  • 故渊
    故渊
    2021-04-23

    <p style="animation: weuiLoading 1s ease-in-out infinite;animation-delay:2s;-webkit-animation-delay:2s;background-color: yellow; color: red; padding: 6px 10px;margin-right: 5px;border-radius: 10%;box-shadow: 0px 0px 9px -2px #000;display: inline-block;">哦~</p>

    2021-04-23
    赞同
    回复
  • 故渊
    故渊
    2021-04-22

    哈哈哈

    2021-04-22
    赞同
    回复
  • 林锦兴
    林锦兴
    2021-04-14

    死翘翘了

    2021-04-14
    赞同
    回复

正在加载...

登录 后发表内容