在上一篇《vue elementUI组件表单动态验证失效的问题与解决办法》中,讲到直接修改prop属性,未触发form-item的重新渲染,所以虽然有校验*的标志,实际上并不会校验。这是表面现象,最近有了空余时间,去看看了element form组件的源码,找到了根本原因。

源码分析

  1. form组件的created钩子函数中添加了el.form.addFieldel.form.removeField事件监听,往fields中添加或删除field,校验的时候会遍历fields数组,而field就是form-item的实例。接着查看form-item组件的源码,可以看到在组件挂载后mounted,如果prop属性有值就会触发el.form.addField事件,在组件销毁前beforeDestroy触发el.form.removeField事件。由此可知如果挂载时form-item组件prop属性无值,不会触发el.form.addField
// form.vue
created() {this.$on('el.form.addField', (field) => {if (field) {this.fields.push(field);}});/* istanbul ignore next */this.$on('el.form.removeField', (field) => {if (field.prop) {this.fields.splice(this.fields.indexOf(field), 1);}});
}// form-item.vue
mounted() {// 重点挂载前有prop属性,才会触发'el.form.addField'if (this.prop) {this.dispatch('ElForm', 'el.form.addField', [this]);// ...this.addValidateEvents();}
},
beforeDestroy() {this.dispatch('ElForm', 'el.form.removeField', [this]);
}
  1. form表单校验是调用表单实例的validate方法,去掉边界、合法性判断一类的代码,其核心源码如下,从代码注释中可以知道,form表单的校验方法核心是调用form-item组件实例的validate方法。
// form.vue
methods: {validate(callback) {// ...this.fields.forEach(field => {// 调用form-item实例的validate方法field.validate('', (message, field) => {if (message) {valid = false;}invalidFields = objectAssign({}, invalidFields, field);if (typeof callback === 'function' && ++count === this.fields.length) {callback(valid, invalidFields);}});});}
},watch: {// 如果rules有变化,强制更新form-item的校验事件,并触发一次form实例validate方法rules() {// remove then add event listeners on form-item after form rules changethis.fields.forEach(field => {field.removeValidateEvents();field.addValidateEvents();});if (this.validateOnRuleChange) {this.validate(() => {});}}
}
  1. 最后看form-itemvalidate方法,省略一些逻辑判断和优化代码,其核心是获取form组件的对应属性的rulesform-item自身的rules,生成AsyncValidator校验器的校验规则描述,并进行数据校验。
// form-item.vue
validate(trigger, callback = noop) {this.validateDisabled = false;// 获取form组件的对应属性的rules及form-item自身的rules,并根据触发器trigger过滤const rules = this.getFilteredRule(trigger);// 判断校验规则,假值或者rules数组为空,则跳过。值得注意的是空对象并不是假值,所以不会跳过if ((!rules || rules.length === 0) && this.required === undefined) {callback();return true;}this.validateState = 'validating';// 设置AsyncValidator的校验规则描述const descriptor = {};if (rules && rules.length > 0) {rules.forEach(rule => {delete rule.trigger;});}descriptor[this.prop] = rules;const validator = new AsyncValidator(descriptor);const model = {};model[this.prop] = this.fieldValue;validator.validate(model, { firstFields: true }, (errors, invalidFields) => {this.validateState = !errors ? 'success' : 'error';this.validateMessage = errors ? errors[0].message : '';callback(this.validateMessage, invalidFields);this.elForm && this.elForm.$emit('validate', this.prop, !errors, this.validateMessage || null);});
}

从上面的第一点中可以看到,因为prop初始值为空字符串'',所以form表单的fileds不会持有该form-item实例,故即使后面修改prop属性,也不会去校验该表单项,导致校验失效。

解决办法

  1. 《vue elementUI组件表单动态验证失效的问题与解决办法》中讲的强制重新渲染form-item,当时不知道根本原因采用的笨办法。
  2. form-item保留prop属性,根据条件动态修改form组件的rules对象。比如下面这样:
watch: {'formData.age': {immediate: true,handler (newVal) {if (newVal >= 18) {this.addRule('bankCardNo', [{ required: true, message: '请输入银行卡号', trigger: 'blur' }])} else {this.addRule('bankCardNo', [])}}}
}data () {return {rules: {}}
},methods: {addRule (prop, rule) {this.$set(this.rules, prop, rule)}
}
  1. form-item保留prop属性,根据条件动态修改form-item组件的rules属性。比如下面两种方式,因为rules属性接受数据和对象。
<el-form-item label="银行卡号" prop="bankCardNo" :rules="formData.age >= 18 ? [{ required: true, message: '请输入银行卡号', trigger: 'blur' }] : []"><el-input v-model="formData.bankCardNo"></el-input>
</el-form-item><!-- 或者 -->
<el-form-item label="银行卡号" prop="bankCardNo" :rules="formData.age >= 18 ? { required: true, message: '请输入银行卡号', trigger: 'blur' } : []"><el-input v-model="formData.bankCardNo"></el-input>
</el-form-item>

总结

终须由浅入深,浮于表面便是管中窥豹,自身还需静下心认真研究

深入了解Element Form表单动态验证问题相关推荐

  1. 关于element form表单的验证错误提示信息位置没有出现在文本框下的问题

    今天带我的大佬碰到一个有意思的坑,现象如图,错误提示没有在文本框下,而是出现在最左边的文字下. 原因:el-form 没有加上 label-width,默认宽度为0,导致验证错误的提示信息直接出现在了 ...

  2. element实现form表单动态添加email效果

    前言: vue中使用element实现form表单动态添加email效果 效果: 实现步骤: 实现源代码: <template><div><el-form ref=&qu ...

  3. layui单选框verify_layui lay-verify form表单自定义验证规则详解

    虽然layui的官方文档已经是写的比较详细,但是初次使用的时候总会懵一下,这里纪录一下lay-verify自定义验证规则的时候到底放哪. html: 提交 js: form.verify({ //数组 ...

  4. element UI 表单自定义验证,css水平且垂直居中方法

    element UI 表单自定义验证 element UI提供了一种内部的表单验证,但是这种方法不能够来进行复杂的验证,如邮箱,手机号等的验证需要用到自定义验证 首先是element UI 提供的基础 ...

  5. element form表单提交数据之后清空所有输入框

    element form表单提交数据之后清空所有输入框 首先el-form标签上的ref属性名和调方法名统一,还有要绑定所有表单数据的一个大对象就是 :model属性,然后prop属性绑定的值要和v- ...

  6. form表单动态设置enctype不生效问题

    问题说明: 在一个form表单中需要发送两种enctype的请求,因此就需要对form表单的enctype进行动态修改.具体做法如下: 1.需要发送application/x-www-form-url ...

  7. 简易封装 element form表单

    1.Form 表单            由输入框.选择器.单选框.多选框等控件组成,用以收集.校验.提交数据 典型表单 包括各种表单项,比如输入框.选择器.开关.单选框.多选框等. 在 Form 组 ...

  8. js中实现form表单动态提交

    最近遇到了调用某银行支付功能的需求 需要使用form表单提交进行传参 记录一下 //创建表单var form = document.createElement("form");// ...

  9. IView的Form表单自定义验证需注意事项

    写自定义验证时,除需要Form中的ref.rules.model和FormItem中的prop数据结构的高度对应外,还要注意,在绑定model中的对应prop之前,还需要清理ref中的fields.否 ...

  10. VUE element-ui之form表单自定义验证11位手机号码(封装验证规则)

    步骤: 封装验证规则: export function isvalidPhone(phone) {const reg = /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2 ...

最新文章

  1. mysql 求数据的长度_mysql 如何求数据的长度
  2. python读取txt文件并写入excel-Python读取txt内容写入xls格式excel中的方法
  3. 人脸识别屡遭非议,会成为“潘多拉魔盒”吗?
  4. 利用python爬虫(part3)--正则表达式
  5. QT —— 应用程序发布
  6. python顺序结构代码_Python代码结构——顺序、分支、循环
  7. java+getactionmap_Struts2 使用OGNL遍历map方法详解
  8. 百度面试题:malloc/free 与 new/delete 的区别
  9. DSP之时钟与定时器之一时钟发生器
  10. webserver接口调用(一)
  11. 利用 JavaScript 快速切换正体中文和简体中文
  12. Cannot mix different versions of joi schemas错误
  13. 3Dmax自动加载脚本错误,语法错误:位于bad,需要因子
  14. Xcode8去除控制台多余打印
  15. 短信接口api发送-kewail
  16. 解析十大网络防骗术 全面防范网络欺诈
  17. 用计算机说出人说的话,用计算机语言说一句情话
  18. 数据挖掘人工神经网络,神经网络的数据处理
  19. 华为云桌面客户端_华为云服务器购买及环境搭建简述
  20. 什么是 Razor?

热门文章

  1. 山东农业大学考研计算机专业分数,山东农业大学研究生分数线
  2. 战争迷雾效果 第1章_要探索,不要地图全开!
  3. 决策树和随机森林预测员工离职率学习代码
  4. ​单页应用程序是如何打破网页设计的?
  5. AndroidQQ登录
  6. 使用SQLite打开本地.db文件
  7. android 自定义数字软键盘,(笔记)Android自定义数字键盘
  8. Leetcode799. 香槟塔
  9. python制作图表放入excel_python- xlsxwriter模块使用(拓展:Excel插入图表)
  10. 设置Button图片位置