如何优雅地离开未保存的表单页面?


需求很常见,就是当用户在表单页面做了编辑操作,但是没保存就离开页面,需要跳出模态框,提醒用户还没保存。

23年的一个React项目也做到了这个需求,当时结合react-router-domant design react Form实现起来非常简单。

  • 路由控制:使用react-router-dom,他提供了Prompt 的组件,这个组件可以在离开当前路由的时候,提示用户,并且阻止路由的跳转。

  • 表单校验ant design react Form,他提供了onValuesChange事件,当字段值更新时触发回调事件

当时我也写了篇文章:react-router-dom中Prompt组件的使用

为什么我强调了ant design react呢?因为我们项目用的ant design vue,而最新版没有类似onValuesChange的属性。

解决方案

  • 路由控制: vue-router中的onBeforeRouteLeave事件,去控制是否拦截路由跳转,单独页面用这个就行,如果页面很多,则建议放在全局路由守卫去做。
  • 表单校验: ant design vue为每个表单的change事件,单独再去做记录输入值的操作。

效果展示

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<a-form
ref="formRef"
:model="formData"
:rules="rules"
size="middle"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<a-form-item :label="t('WorkCenter.Ctl.Remark')" name="Memo">
<a-textarea
v-model:value="formData.Memo"
:placeholder="t('WorkCenter.Ctl.RemarkPlaceholder')"
:rows="5"
@change="handleMemo"
/>
</a-form-item>
...其余表单
</a-form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import { onBeforeRouteLeave } from 'vue-router'; 

const formData = reactive({ // 绑定表单值
CleanupReason: '',
});

const originalValues = reactive({ // 记录输入值
CleanupReason: ''
});

// 记录输入值
const handleMemo = (e) => {
originalValues.CleanupReason = e.target.value
}

// 深度比较
const deepCompare = (a, b) => {
return JSON.stringify(a) === JSON.stringify(b);
};

// 离开路由前事件触发
onBeforeRouteLeave((to, from, next) => {
const isModified = handleFieldsChange(); // 先去比较表单是否和原来不一致
if (isModified) {
Modal.confirm({
title: '提示',
content: '当前页有未保存的内容,确定离开?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {
next(); // 允许跳转
},
onCancel() {
console.log('Cancel');
},
});
} else {
next();
}
});

这样我们的需求就完成了。

这篇文章的标题呢… 不是给出了优雅的解决方案,而是再寻求更优雅的解决方案。哈哈

哦对了,我最近开发了一个叫牛马工作器的chrome拓展插件,很好玩哦,感兴趣的话,给我的公众号回复牛马即可免费获取。

我的微信公众号: 梨的前端小屋


  目录