ElementUI的表单验证失效,出现意想不到的问题
起因
项目中有一个心理测试模块,需要实现修改功能。
尝试一
页面渲染之前,created时,发送一个请求,拿到该测试问卷的基本信息(名称、简介、测试结果等),该值命名为testData。
created(){
const data = {
params: {id: this.$route.query.id}
}
this.apiGet('***/***/getQuestionById', data).then(res => {
this.testData = res.data[0]
}
}
问题
点击修改问卷,让form表单里填充testData的值。这样bug就来了,我在form表单里修改testData.title的值的同时,页面左上角的title也跟着改变。因为左上角的值和input框里的值绑定的是同一个值,这时,如果我在input框里修改title的值,但是点击取消,不提交表单。按需求来说,该title是不应该被修改的,但是实际上被修改了。这时,用户只能通过刷新的方式,重新获取该问卷的基本信息。
解决
我想到可以用vue里的.lazy方式,让输入框里的值在修改的同时,左上角的值不会同时改变。但是一旦input框失去焦点,该值还是被改变了。所以这样也行不通。
尝试二
我重新申请一个变量formData,用来存放testData。此处一定要注意通过 值引用 赋值,不要把地址赋值过去了。在尝试一中,created时,获取到testData后,就给formData赋值。
created(){
const data = {
params: {id: this.$route.query.id}
}
this.apiGet('***/***/getQuestionById', data).then(res => {
this.testData = res.data[0]
}
this.testForm.title = this.testData.title
this.testForm.abstract = this.testData.abstract
this.testForm.value = this.testData.value
this.testForm.result = this.testData.result
}
表单部分代码如下
<el-dialog title="修改测试问卷" :visible.sync="dialogTestVisible" width="40%">
<el-form :model="testForm" ref="editTestForm">
<el-form-item label-width="18%" label="问卷名称:" prop="title"
:rules="{ required: true, message: '问卷名称不能为空', trigger: 'blur' }">
<el-input v-model="testForm.title" autocomplete="off" placeholder="输入问卷名称"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" class="pull-left" @click="addDomain()">新增选项</el-button>
<el-button class="pull-left" @click="resetForm('editTestForm')">重置选项</el-button>
<el-button @click="dialogTestVisible = false">取 消</el-button>
<el-button type="primary" @click="editTestDialog('editTestForm')" :loading="isLoading">确 定</el-button>
</div>
</el-dialog>
表单提交代码
editTestDialog(formName){
this.$refs[formName].validate((valid) => {
if (valid) {
const data = {
id: this.id,
type: 0,
title: this.testForm.title,
abstract: this.testForm.abstract,
value: this.testForm.value,
result: this.testForm.result
}
this.apiPost('admin/MentalTest/QuestionEdit',data).then((res) => {
this.handelResponse(res, (data) => {
if(res.code === 200){
_g.toastMsg('success', "修改试题成功")
this.dialogTestVisible = false
setTimeout(() => {
_g.shallowRefresh_({name: this.$route.name, query: this.$route.query})
}, 0)
}else{
_g.toastMsg('error', "修改试题失败")
}
})
})
} else {
_g.toastMsg('error', "修改试题失败")
return false;
}
});
}
问题
点击修改,模态框里都能正确渲染该问卷的数据,但是这时表单的验证不起作用了。input框值为空,验证能通过,input框值不为空时,验证不通过,提示值为空。
情况一
点击修改,模态框正确渲染数据后,把input框置空,不提示input框值为空。此时,点击提交,valid为true,表单成功提交,title的值被修改成了空。表单验证出了问题,我一步步排查也排查不出来到底是哪出了错。
情况二
基于上面的情况一,测试问卷的title被修改成了空。
点击修改,模态框正确渲染数据,input框值确实为空。但是如果在input框里输入值,点击提交,表单却验证不通过,valid为false,无法提交表单。
解决
我一直都怀疑是自己某个地方出现了低级的拼写错误,但是一个字母一个字母检查,确实没有错误,但是又找不到其他错误。而且,其他的表单验证很正常,都是相同的逻辑。比如,表格里的修改,就是修改该测试问卷某一个问题的信息(如问题内容,选项内容,选项分值等),该表单验证非常顺利,和预想的一样,input值为空,提示不能为空,不为空时,表单顺利提交。
对比两个表单,逻辑是一样的,但是前者表单验证就出现了错误。我也对比了两个表单的代码,思路一模一样,也没有任何低级错误。
最后,我想到了一个 不同之处!!!
点击修改问卷前,formData就已经有值了,点击修改问卷后,数据渲染。
而表格里的修改呢?点击修改之后,会发送一个请求,根据id获取该题目的信息,然后数据渲染到表单上。
尝试三
在点击修改问卷后,重新发送一次请求,获取该问卷的信息,赋值给formData。而不是在整个页面渲染之前,获取到testData之后就赋值给formData。这样,既不会有尝试一中出现的,左上角的title随着input框里的值改变而改变,也不会有尝试二中出现的,表单验证出错。
修改后的代码如下
不在created时获取fromData,而是在触发点击,editTestBtn函数中,重新发送请求,获取testForm。
editTestBtn(){
this.dialogTestVisible = true
// 获取该问卷的基本信息
const data = {
params: {
id: this.$route.query.id
}
}
this.apiGet('***/***/getQuestionById', data).then(res => {
this.testForm = res.data
})
}
总结
虽然表单验证bug解决了,但是为什么会造成,表单验证出错,这种情况,我还了解的不够深入,希望有大神指点!