Ios、Android微信浏览器后退跳转实现,及遇到的bug

3,773 阅读3分钟

一、需求背景

  • 1、当前页有一个弹窗,当用户浏览器后退的时候不希望直接退出,而是将当前弹窗进行关闭,留在当前页
  • 2、用户进入当前页点击浏览器后退的时候不希望用户直接退出,使用浏览器后退跳转到其它页面,增加流量

二、功能实现

使用浏览器API window.history 进行后退控制,需要浏览器支持history(大部分移动浏览器都支持了) 代码示例:

// 添加浏览器历史纪录
history.pushState('test', '', '')
// 监听浏览器后退事件
window.onpopstate = function (e) {
  // 这里进行业务逻辑的处理
  location.href = 'c.html'
}

这样在页面加载的时候添加入新的浏览器纪录就可以在后退的时候触发 popState 事件,然后处理你的业务逻辑

三、遇到的BUG

  • 1、history.pushState在当前页面刷新一次页面就会添加一次,当多次刷新的时候会将history的长度加长,需要使用一个存储变量进行判断是否需要添加历史纪录,显然H5新接口sessionStorage很适合当前使用,这样在跳转到后退页面之后在使用浏览器后退会返回到当前页,由于使用了判断是当前页不再进行历史压栈,就不会在重新触发popState事件了,避免了无限次浏览器后退无限循环。
let active_view = sessionStorage.getItem('active_view')
if (!active_view) {
  sessionStorage.setItem('active_view', 'has')
}
  • 2、Ios微信浏览器popstate的bug,在当前A.html页跳转到b.html页,然后再b.html页通过浏览器返回按钮回到a.html页面的时候会直接触发popState事件,直接跳转到c.html页面了,真实需求是再b.html返回的时候回到a.html页面,然后在a.html页面的后退的时候才进行跳转c.html页面。所以我将Ios和Android区分开来,分别进行不同的业务处理。
// 判断ios 的时候在第二次返回才进行页面跳转,不是的在重新将history增加
let jumps: any = sessionStorage.getItem('jump_number') || 0;
    let count = parseInt(jumps) + 1;
    let u = navigator.userAgent;
    let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    sessionStorage.setItem('jump_number', count);
    if (isIOS) {
      if (count >= 2) {
        // ios
        setJump();
      } else {
        pushHistory();
      }
    } else {
      // 其它
      setJump();
    }

参考了 IOS微信浏览器返回事件popstate监听

  • 3、页面跳转问题,在微信浏览器中直接使用location.href = c.html有可能页面不会替换,其实显示的还是a.html,需要点击刷新页面才是c.html,所以封装了一个跳转函数,加上一段打印log就可以正常跳转了
// 需要将url打印出来页面跳转才会正常,(发稿之前还未弄清楚是什么原因,以后知道了在附上)
function setJump(url) {
  // 跳转
  console.log('链接:' + url);
  window.location.href = url;
}
  • 4、当使用history.pushState(state, "test", "#")添加参数的时候,如果当前页面的url中有#号,就是最后一个参数和url中最后的字符相同,会破坏popState事件,可能导致不触发,因此使用参数加入历史的需要注意投放链接的url,Android 手机部分机型在此情况下点击浏览器后退也会触发两次popState事件
// push 浏览器历史记录
function pushHistory() {
  let state = {
    title: "test",
    url: "#"
  };
  window.history.pushState(state, "test", "#")
}

总结

  • 1、H5 页面需要在很多平台进行运行,有些是微信、支付宝内置浏览器的问题,也有很多是手机平台的问题,需要兼容许多机型和平台的问题,比较复杂还有更多的平台兼容问题需要去处理。
  • 2、不同平台对于window的API有一些差异,许多BUG都是该差异引起的,所以在遇到的时候多查查资料就可以了。

开发环境的问题

  • 1、大多数前端同学都是使用谷歌浏览器作为开发浏览器的。新版的谷歌浏览器点击后退按钮不会触发popState事件,需要在控制台打印history.length在点击后退按钮才会触发(还不知道这个原因是什么)