H5 挽留弹窗的设计与实现
背景
运营提出想在用户点击退出,返回的时候,弹窗挽留用户,并通过挽留弹窗引流一些产品,提高转换率,因此挽留弹窗需要实现以下功能,用户点击返回的时候,弹出挽留弹窗。
方案初步设计
经过本人的调研,浏览器没有直接提供类似用户退出的事件监听,因此端外实现的方案都是比较hack的方案。
主要借助history这个API,使用到以下两个方法
- history.pushState():往浏览器里插一条历史记录
- window.addEventListener(‘popstate’, (e) => {}) :监听浏览器历史记录变化
进入页面后通过history.pushState(null, null, window.location.href)
,往页面中插一条和本页面一样的记录(相当于克隆了一下页面),此时我们的页面会存在两个相同的历史记录。
因此用户再点击回退的时候,不会退出页面,而且又触发了popstate事件,我们就可以在popstate事件的回调里处理我们的弹窗逻辑了。
其实除了借助pushSate克隆页面,我们也可以通过加一个不触发页面重新渲染的hash变量来克隆一个页面(hash的方式兼容性更好),但添加hash变量的方式会对采取hashRouter路由方案的应用有影响,因此可以根据自己的业务来使用不同的技术方案
思路如下图所示:
代码实现:
// 初次进入页面后克隆一条记录
history.pushState(null, null, window.location.href);
// 注意这里需要延迟调用事件监听函数
// 原因是有些场景下,初次进入页面也会触发popstate事件
setTimeout(() => {
window.addEventListener('popstate', e => processRetain(e))
}, 500)
const processRetain = () => {
// 这个函数内控制弹窗的显示,处理相关业务逻辑
}
存在的问题
上述方案在不同的浏览器显示机制会出现较为诡异的bug
- 有些场景,初次打开页面也会触发popstate事件,这个可以通过延迟定时器解决大部分情况,但有时还是会出现,目前不知原因
- 如果页面是通过js跳转得来的,并不是用户手动点击打开的页面,点击后退时不一定会触发
popstate
事件,这种情况较为罕见,目前也不知道怎么解决
上述两个问题可以通过采取插hash
而不是插history
记录的方式解决,但本人业务需求无法使用hash这种方式,因此还是妥协性的使用了history