前言:
在前端项目开发过程中,经常要使用 element-ui 库中的 el-form 组件,而这个组件有一个内置方法resetFields(),这个函数是用来重置表单项中的所有数据,这里的重置并非将字段全部置为空,而是根据开发者在页面设置的默认初始值去重置的,也就是根据 data() 体中 return 设置的初始值来重置。但在 resetFields() 的使用过程中,偶尔是会出现 TypeError: Cannot read properties of undefined (reading 'resetFields') 的错误,有时也会出现没报错但是表单数据却依然没有清空的情况,本文搜集了四种情形(最后一种情形最常见),然后给出了解决方案。
情形一:
<template>
<div>
<el-form v-if="formShow" ref="form" :model="formInfo">
<el-form-item label="fruit" prop="fruit">
<el-input v-model="formInfo.fruit"></el-input>
</el-form-item>
<el-form-item label="price" prop="price">
<el-input v-model="formInfo.price"></el-input>
</el-form-item>
</el-form>
<el-button @click="reset">重置</el-button>
</div>
</template>
<script>
export default {
name: 'goods',
data() {
return {
formShow: false,
formInfo:{
fruit: '',
price: 0
}
}
},
methods: {
reset() {
this.$refs['form'].resetFields()
console.log("重置后:",this.$refs['form'])
}
}
}
</script>
上述代码是有问题的,会出现 TypeError 错误,问题出在 v-if="formShow" 上,formShow 为false,因此表单相当于是不存在的,那么 this.$refs['form'] 就会为 undefined,它没有 resetFields() 方法,修改方法有两种,一是将 v-if 改为 v-show,为什么 v-show 就有用,请自行网上搜索 v-if 与 v-show 的区别,此处不做过多解析,另一种方法是重写 reset() 方法,改为如下:
reset() {
if(this.$refs['form'] != undefined){
this.$refs['form'].resetFields()
}
}
情形二:
使用 el-form 组件去封装了一个自定义的组件,以为自定义的组件默认也有 resetFields() 方法:
<template>
<div>
<self-form ref="form" :model="formInfo" :data="formData">
</self-form>
<el-button @click="reset">重置</el-button>
</div>
</template>
<script>
export default {
name: 'goods',
data() {
return {
formData: '',
formInfo:{
fruit: '',
price: 0
}
}
},
methods: {
reset() {
this.$refs['form'].resetFields()
console.log("重置后:",this.$refs['form'])
}
}
}
</script>
上述代码也是有问题的,原因在于自定义的组件 self-form 里并没有自定义一个重置函数,打个日志 (console.log(this.$refs['form'])) 会发现控制台显示的 this.$refs['form'] 压根就没有resetFields() 方法,因此需要自己写一个该方法一同封装进去,假如自定义的组件文件名为:selfForm.vue,那么在该文件里附上如下代码:
<template>
<div>
<el-form ref="form1" :model="formInfo">
<el-form-item label="fruit" prop="fruit">
<el-input v-model="formInfo.fruit"></el-input>
</el-form-item>
<el-form-item label="price" prop="price">
<el-input v-model="formInfo.price"></el-input>
</el-form-item>
</el-form>
<el-button @click="reset">重置</el-button>
</div>
</template>
<script>
export default {
name: 'selfForm',
data() {
return {
formShow: false,
formInfo:{
fruit: '',
price: 0
}
}
},
methods: {
resetFields() {
this.$refs['form1'].resetFields()
console.log("重置后:",this.$refs['form1'])
}
}
}
</script>
我们在使用 element-ui 里的组件去封装自己的组件时一定要注意内置方法都要重新实现一遍,不然都是未定义的。
情形三:
第三种情形比较简单:
<template>
<div>
<el-form ref="form" :model="formInfo">
<el-form-item label="fruit" prop="fruit">
<el-input v-model="formInfo.fruit"></el-input>
</el-form-item>
<el-form-item label="price" prop="price">
<el-input v-model="formInfo.price"></el-input>
</el-form-item>
</el-form>
<el-button @click="reset">重置</el-button>
</div>
</template>
<script>
export default {
name: 'goods',
data() {
return {
formInfo:{
fruit: '',
price: 0
}
}
},
methods: {
reset() {
this.$refs['form'].resetFields()
console.log("重置后:",this.$refs['form'])
}
}
}
</script>
上述代码在某些情况会出现 TypeError 的错误,原因可能在于 dom 未获取到相应的值就去访问,导致 this.$refs['form'] 为 undefined,这个时候需要在外面加层 nextTick 去包裹,代码如下:
methods: {
reset() {
this.$nextTick(() => {
this.$refs['form'].resetFields()
console.log('重置后:', this.$refs['form'])
})
}
}
情形四:
情形四就是忘了在每个表单项中添加 prop 属性,这种情况处理最简单但是容易被开发者遗漏,遗漏也不会报错只是达不到应有的效果,见如下代码(未添加 prop 属性):
点击 RESET 按钮后结果如下(表单数据打印出来是不为空的,说明 resetFields() 方法失效了,也没有报错信息):
添加上 prop 属性后的代码如下:
加上 prop 后点击RESET按钮的结果如下: