微信安卓popstate后退导致页面刷新解决方案

4,463 阅读2分钟

问题描述:

安卓机微信版本号为7.0.47.0.8下监听popstate事件时,当点击物理键返回时,浏览器会强制页面刷新,导致popstate中定义的一些事件因为刷新而受影响,比如出现弹窗闪退现象。

解决方案

  • popstate中使用localStorage.setItem,当页面刷新之后拿到localStorage.getItem的值,可以判断是否点击物理键(即返回按钮)返回的。
  • 此方法对有问题的版本号进行兼容操作,通过也可以兼容ios或安卓其他版本号的返回事件。
var wxPopState = (function() {
	// 返回时浏览器强制刷新的微信版本号
	var problemVersions = ['7.0.4', '7.0.5', '7.0.6', '7.0.7', '7.0.8'];
	// 设置缓存的key值
	var setItemKeyName = '_wx_popstate';
	// 判断当前是否为有命中的版本
	var isProblemVersion = !!~problemVersions.indexOf(getWxVersion()) && isAndroid();
	// 处理后返回刷新的回调,即相当在popstate中定义的事件
	var callback = null;

	// 获取微信版本号
	function getWxVersion() {
		return navigator.userAgent.match(/MicroMessenger\/(\d+\.\d+\.\d+)[\.\s]?/)[1];
	}
	// 是否安卓
    function isAndroid() {
        return /android/i.test(navigator.userAgent)
    }

	// push历史栈
	function pushState() {
		var state = {
			title: "",
			url: "#"
		};
		window.history.pushState(state, state.title, state.url);
	}

	return {
		register: function(options) {
			var needPushState = options.needPushState;
			callback = options.callback;
			if (!callback) {
				return
			}
			if (needPushState) {
				pushState();
			}
			// 通过setItemKeyName的值可以判断是否为按键返回的。
			// 如果值存在,将执行后退定义的事件,并且不再注册返回事件和推入历史栈。
			// 如果值不存在,将注册返回时需要设置的操作。
			if (localStorage.getItem(setItemKeyName)) {
				this.popstateEven();
				var that = this;
				setTimeout(function () {
				    // 由于返回时页面会刷新一遍,导致历史栈加1,所以要进行减1操作
					that.popState()
				}, 0)
				return
			}
			window.addEventListener('popstate', function() {
				// 有问题版本的处理
				if (isProblemVersion) {
					// 设置这一步非常重要,为了判断是否为按键返回的
					localStorage.setItem(setItemKeyName, '1');
					// 这一步的目的是以上有问题的版本返回时会刷新
					// 为确保其一定刷新操作,可以考虑设置以下方法
					window.location.reload();
					return
				}
				// 非问题版本将进行正常注册逻辑
				callback && callback();
			})
		},
		popState: function() {
			window.history.go(-1);
		},
		popstateEven: function() {
			if (!isProblemVersion) {
				return
			}
			// 以上版本物理返回时将执行register里定义的callback函数
			callback && callback();
			localStorage.setItem(setItemKeyName, '');
		}
	}
})();

wxPopState.register({
	needPushState: true, // 是否需要推入历史栈,如果页面中已有此操作,则可忽略此参数
	callback: function() {
		// do something
	}
});

参与贡献者:zeifenbing

参考资料


如需转载,请注明来源。

如有纰漏,请在留言区留言哦。