开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
当网页打开标签很多时,点击关闭标签页面很容易误触到其他页面,如果页面有比较多的表单数据没有保存,可能造成数据丢失,给用户带来不好的体验
而解决这个方法通常有两种方法:
- 自动保存到草稿箱,像掘金发布文章时会自动保存,需要前后端功能开发支持
- 关闭页面时提示,关闭或刷新页面时进行弹窗确认,用户确认后再继续操作,提示类似于:
关闭页面时提示几乎没有什么开发成本,所以在缺乏功能开发支持的情况下,采用这种方案更合适
实现
window对象的beforeunload事件会在页面关闭或刷新(页面卸载)前触发,可以通过该生命周期实现关闭前的提示
window.addEventListener('beforeunload', (e) => {
const tips = '要離開網站嗎?系統可能不會儲存你所做的變更。'
e.preventDefault()
e.returnValue = tips
return tips
})
根据规范,应该实现 e.preventDefault()
,尽管在多数浏览器中测试,是否阻止其默认行为并不影响最终结果,但是从语义上 e.preventDefault()
是合理的。
在一些浏览器会可以允许设置自定义提醒文案,把弹窗显示的提醒文案赋值给 e.returnValue
以及 return出去,虽然绝大多数浏览器已不再支持自定义文案,但也仍需要写这样的代码才能触发弹窗。
小坑
- 表单提交成功后,拦截并不会被取消 采用这样的拦截,是为了提醒用户还未保存时避免误操作,如果页面已经明确提交了,应该取消这个事件:
function beforeunload(e) {
const tips = '要離開網站嗎?系統可能不會儲存你所做的變更。'
e.preventDefault()
e.returnValue = tips
return tips
}
window.addEventListener('beforeunload', beforeunload)
function submit() {
window.removeEventListener('beforeunload', beforeunload)
}
- 拦截触发条件:页面与之交互,通常只要页面被点击过,页面卸载时才会触发弹窗。
- beforeunload 事件中不能使用alert等window其他弹窗,alert不会被触发且控制台报错,但能正常关闭拦截
- 纯前端渲染项目中,跳转路由并不会触发 beforeunload 事件。 比如vue项目中,通过vue-router跳转项目路由时,其实页面并没有被关闭、刷新或卸载,事件自然不会被触发,可以通过路由导航守卫进行拦截处理