elementUI是我们前端常用的UI框架,在使用它的过程中,或多或少都会踩一些坑,有的坑是我们自己代码失误造成的,有的是组件自身的问题。
这次,在同一个项目中,我接连两次掉坑,居然都是因为自身代码问题,也是醉了。以下就是我此次掉坑的全记录,希望大家不要重复踩坑。
一、千万不要用formData = {} 来暴力清空 el-form表单数据
通常,我们在关闭表单弹框之前,都会清除表单数据(这里说的清除,其实是表单重置,让其恢复到初始状态)。这样做的目的有两个:
1.避免再打开弹框时,上一次填写的内容还在。
2.避免上一次被赋值的数据,错误地传给了后端。
一般情况下,我们会这样处理:
export default {
data() {
return {
formData: {
departId: '',//与prop绑定
departName: '',
}
}
}
methods:{
handleClose() {
this.$refs.form.resetFields(); // 关键代码
this.isVisible = false;
},
}
}
但大家都知道,表单有时候会因项目需求,写的很复杂,总有几个数据无法通过this.$refs.form.resetFields()来清除。
比如,某个属性,为了统一管理,我们在formData里声明了,但不能写在el-form-item的prop属性里,如上面代码中的departName属性,这时,我们通过this.$refs.form.resetFields()就无法清除该属性的值。
所以就出现了formData = {} 这种省事且暴力的写法。
一开始,也没发现问题,但多操作几次表单,就会出现表单校验异常、表单不能正常填写等问题。因为formData中的属性被暴力清除了,导致el-form的响应出现问题。
正确的做法是:
先用ElementUi提供的方法统一清除,如下:
this.$refs.form.resetFields();
不能清除的,则如下逐个清除:
this.formData.departName = ''
二、千万不要让resetFields() 与formData提交处于同步任务中
一般情况下,我们都是走后端接口来提交formData,然后等接口请求成功后,再用resetFields()来让表单恢复到初始状态,最后关闭弹框。
一直以来,我也是这样做的,但是最近在写一个表单时,就出现了问题。
场景是这样的:
先写一个弹框表单,然后将填写好的表单数据回显在一个表格中,等表格内容确认无误后,再将表格数据一起提交给后端接口。
关键代码如下:
export default {
data() {
return {
formData: {
departId: '', // 与prop绑定
departName: '',
nodeName: '', // 与prop绑定
}
}
}
methods:{
handleClose() {
this.$refs.form.resetFields();
this.isVisible = false;
},
handleOk() {
this.$refs.form.validate((isPass, val) => {
if(isPass) {
this.$emit('handleAddOk', this.formData)
this.handleClose()
}
})
}
}
}
等所有代码写完之后,departName可以在表格中正常回显,但是nodeName这个字段的值,怎么也回显不了在表格中。
排查了一下,nodeName在执行handleOk这个方法时,被清空了。
怎么就被清空了呢?
原来,resetFields()清空的表单对象与this.$emit提交的formData都属于同一个堆内存对象,当用resetFields()清空了表单对象时,也就影响了this.$emit提交的formData。
注意,以下写法,也会存在上述问题,因为依旧是同一个堆内存对象:
this.formData.departId = ''
this.formData.departName = ''
this.formData.nodeName = ''
所以最终改成了以下写法:
this.formData = {
departId: '',
departName: '',
nodeName: ''
}
也就是,将formData重新赋值,变成了一个新对象。这样,上述问题就完美解决了。
============ 2023年4月19日更新 ============
经评论区的掘友提醒,可以用this.$options.data()来重置数据,我实践了一下,的确可以,故此更新记录一下。
而我前文提到的方法,在数据不多时我们可以采用,但数据较多的情况下,还是建议用下面的方法。
1.重置data中的所有数据
Object.assign(this.$data, this.$options.data())
this.$data:是现阶段的data数据,就是改变后的data数据this.$options.data():是原始的data数据,就是页面刚加载时的data
- data中若使用了this来访问props或methods,在重置options.data()的this指向,最好使用this.$options.data.call(this)。
2.重置data中的一个数据
Object.assign(this.formData, this.$options.data().formData)
this.formData = this.$options.data().formData
当我们采用以上方法重置表单数据时,我们可以采用下面方法重置表单校验:
this.$refs.form.clearValidate()