场景

近期工作中有一个需求,在小程序的多个页面添加一个可关闭的悬浮窗,这个悬浮窗结构简单,是由一张图片和一个关闭按钮组成,点击图片会跳转到活动页面的web-view。现在的需求是在某个页面关闭这个悬浮窗后,所有页面不再显示,直到下次进入小程序。

问题

需求看起来不是很难,只要在全局状态管理设置一个悬浮窗是否显示的状态即可,但实际开发中还是遇到了一些问题。也是小程序比较坑的一些地方。

  1. 除非你重新进入小程序,不然vuex保存的状态将继续留存
    通过右上角右边按钮返回微信界面,会触发App.onHide(), 这时候小程序只是隐藏到后台,vuex保存的状态继续存在,这就造成了,我关闭活动悬浮窗后,点右上角返回微信,再次进入小程序时,悬浮窗没有出现。为了解决这个问题,我在App.onShow()设置了每次应用显示在前台时,将悬浮窗状态设置为“显示”,这样做后,现在无论关不关闭悬浮窗,每次进入小程序悬浮窗都会显示,但是,另外一个问题出现了。
  2. 通过右上角左边按钮分享页面时,也会触发App.onHide(),分享返回时,也会触发App.onShow()
    就是说,如果我关闭了悬浮窗,分享页面返回后,悬浮窗又会出现,这明显不太合理,因为需求的意思是,一旦关闭悬浮窗,在本次的小程序体验中,悬浮窗就不再出现。这个问题提取出来就是,小程序没有办法分辨你是右上角“退出”小程序后再进入小程序,还是分享完界面回来,因为这两种行为都会触发应用级的onHide()和onShow(),页面级的onHide() onShow()就更不用说了。
    解决方法:在页面的onShareAppMessage()方法中先判断当前悬浮窗的状态是否为“隐藏”,如果是的话,设置该页面data中shareBack=true(初始化为false),然后在这个页面的onShow()方法中,判断 if(this.shareBack), 为真说明是分享回来的,我们将悬浮窗的全局状态重新设置为“隐藏”(因为在应用级的onShow()方法中,我们统一将悬浮窗设置为“显示”了,应用级的onShow比页面级的onShow先调用,我们后设置的值可以覆盖),然后我们再将this.shareBack = false
    代码如下:

页面

onShow(){  
	if(this.shareBack){
		this.shareBack = false
		this.$store.dispatch('set_close') // 设置为隐藏状态
	}
},
// 监听页面分享
onShareAppMessage: function () {
	if(!store.state.show){
		this.shareBack = true
	}
},

App.vue

onShow() {
	console.log('App Show,app展现在前台')
	this.$store.dispatch('set_open') // 设置显示状态
},