Vue2.5.1+iView4.0.0切换表单后隐藏字段校验提示异常求助
问题根源与解决办法
这问题我之前碰到过类似的,本质是iView Form的校验逻辑加上v-if切换组件时的状态残留导致的,咱们来拆解下:
为啥会出现这个情况?
- 共用校验规则的全局校验:你两个表单都绑了同一个
ruleCustom,里面肯定包含了usage的必填规则对吧?当切换到met_type=3时,虽然对应的Usage输入框没渲染,但Form组件会基于绑定的model和rules做全量校验——这时候form_data没有usage属性,直接触发了必填校验,所以错误提示就冒出来了。 - v-if切换时校验状态没清干净:iView的Form组件在v-if切换(组件销毁重建)时,有时候校验状态不会自动完全清除,旧的提示就残留下来了。
具体解决方法,按推荐度排序:
1. 给不同表单配独立的校验规则(最推荐)
既然两个表单的字段完全不一样,没必要共用一套规则,拆开来更清晰:
// 在组件的data里定义两套规则 data() { return { // 对应met_type=2的表单规则 ruleForType2: { usage: [ { required: true, message: 'usage is required', trigger: 'blur' } // 这里加type=2表单其他字段的规则 ] }, // 对应met_type=3的表单规则 ruleForType3: { item: [ { required: true, message: 'item is required', trigger: 'blur' } // 这里加type=3表单其他字段的规则 ] } } }
然后模板里分别绑定对应的规则:
<div v-if="met_type==2"> <Form :rules="ruleForType2" :model="form_data"> <!-- type=2的表单内容 --> </Form> </div> <div v-if="met_type==3"> <Form :rules="ruleForType3" :model="form_data"> <!-- type=3的表单内容 --> </Form> </div>
这样每个表单只会校验自己需要的字段,从根源上杜绝了无关字段的校验触发。
2. 切换表单时手动重置校验状态
要是不想拆分规则,那就切换后手动清掉表单的校验状态。先给两个表单加ref:
<div v-if="met_type==2"> <Form ref="formType2" :rules="ruleCustom" :model="form_data"> <!-- ... --> </Form> </div> <div v-if="met_type==3"> <Form ref="formType3" :rules="ruleCustom" :model="form_data"> <!-- ... --> </Form> </div>
然后在loadData方法里,设置完met_type后,等组件渲染完再调用resetFields:
loadData: function(met_type) { dataUtils.fetch(this.met_id, met_type, (retVal) => { this.form_data = retVal.data; this.met_type = met_type; // 等DOM更新完成后重置表单 this.$nextTick(() => { const currentForm = this.$refs[`formType${met_type}`]; if (currentForm) { currentForm.resetFields(); } }); }); }
resetFields会清除表单的所有校验状态,刚好能解决残留提示的问题,而且你的输入框是readonly,重置字段值也不会有影响。
3. 动态切换校验规则(备选)
还有一种方式是根据met_type动态修改ruleCustom的内容,只保留当前表单需要的规则:
loadData: function(met_type) { dataUtils.fetch(this.met_id, met_type, (retVal) => { this.form_data = retVal.data; this.met_type = met_type; // 动态更新规则 if (met_type === 2) { this.ruleCustom = { usage: [/* 原usage的必填规则 */], // 其他type=2的字段规则 }; } else if (met_type === 3) { this.ruleCustom = { item: [/* item的必填规则 */], // 其他type=3的字段规则 }; } // 同样要等DOM更新后重置表单 this.$nextTick(() => { const currentForm = this.$refs[`formType${met_type}`]; currentForm?.resetFields(); }); }); }
不过这种方法需要维护规则的动态切换,代码复杂度比第一种高,所以更建议用拆分规则的方式。
额外小提醒
- 确保
retVal.data是一个新对象(如果后端返回的是新对象就没问题),避免因为对象引用没变化导致Form没感知到model更新。 - 你表单里的
required属性可以只在rules里配置,FormItem的required会和rules联动,统一在rules里管理更清晰。
内容的提问来源于stack exchange,提问作者George Wei
相关产品推荐
相关产品推荐

