Vue离开页面时提示是否保存


这个问题源自这个博客,之前编写的时候偷懒自己用的东西搞那么严谨干啥没做保存提醒处理。之后因为各种没长脑子包括但不限于直接关闭浏览器等导致写了一大半的文章功亏一篑(泪目),一气之下决定还是要完善一下这个功能。

思路

首先整理一下需要解决的问题:

  • 离开路由时弹窗提示
  • 关闭页面时系统弹窗提示
  • 内容未修改时不需要提示

解决方案

首先定义一个页面内容初始值

1
2
3
4
5
6
7
const defaultFormData = {
title: '',
categories: [],
tags: [],
content: '',
createTime: null
}

在data中给表单数据存储表单状态数据对象赋予深克隆后的初始值

1
2
3
4
5
6
7
8
data() {
return {
// 表单数据对象
formData: JSON.parse(JSON.stringify(defaultFormData)),
// 初始表格数据,用于判断是否存在修改,退出时给予警告
initFormData: JSON.parse(JSON.stringify(defaultFormData))
}
}

编写保存状态方法,将表单状态数据重置为当前表单数据,用于保存等操作时执行

1
2
3
4
    // 保存页面当前状态(用于检查是否存在变动)
savePageState() {
this.initFormData = JSON.parse(JSON.stringify(this.formData))
}

编写检查方法,检查当前页面内容是否存在变动
isEqualObj方法是上一篇文章所写的对比对象的值是否相等的方法,传送门

1
2
3
4
5
6
7

// 检查页面内容是否存在变动
checkPageChange() {
const trueFormData = JSON.parse(JSON.stringify(this.formData))
return !isEqualObj(this.initFormData, trueFormData)
}

路由离开时处理

使用组件内路由导航守卫beforeRouteLeave检测路由离开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 离开前警告
beforeRouteLeave(to, from, next) {
if (this.checkPageChange()) {
this.$confirm('文章没写完呢,不要啦?', '提示', {
confirmButtonText: '手滑了',
cancelButtonText: '不要了',
type: 'warning'
}).then(() => {
// 选择'手滑',取消路由跳转
next(false)
}).catch(() => {
next()
})
} else {
// 内容未改变,直接放行
next()
}
}

页面关闭时处理

mounted生命周期中给windows挂载onbeforeunload事件监听页面关闭

1
2
3
4
5
6
7
8
9
10
mounted() {
this.init()
// 未保存退出报警
window.onbeforeunload = e => {
if (this.checkPageChange()) {
e = window.event || e
e.returnValue = ('确定离开当前页面吗?')
}
}
}

同时不要忘了在组件注销时移除监听事件,在beforeDestroy生命周期内处理

1
2
3
beforeDestroy() {
window.onbeforeunload = null
}