深入了解Element Form表单动态验证问题
在上一篇《vue elementUI组件表单动态验证失效的问题与解决办法》中,讲到直接修改prop
属性,未触发form-item
的重新渲染,所以虽然有校验*
的标志,实际上并不会校验。这是表面现象,最近有了空余时间,去看看了element form
组件的源码,找到了根本原因。
源码分析
- 在
form
组件的created
钩子函数中添加了el.form.addField
和el.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]);
}
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(() => {});}}
}
- 最后看
form-item
的validate
方法,省略一些逻辑判断和优化代码,其核心是获取form
组件的对应属性的rules
及form-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
属性,也不会去校验该表单项,导致校验失效。
解决办法
- 《vue elementUI组件表单动态验证失效的问题与解决办法》中讲的强制重新渲染
form-item
,当时不知道根本原因采用的笨办法。 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)}
}
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表单动态验证问题相关推荐
- 关于element form表单的验证错误提示信息位置没有出现在文本框下的问题
今天带我的大佬碰到一个有意思的坑,现象如图,错误提示没有在文本框下,而是出现在最左边的文字下. 原因:el-form 没有加上 label-width,默认宽度为0,导致验证错误的提示信息直接出现在了 ...
- element实现form表单动态添加email效果
前言: vue中使用element实现form表单动态添加email效果 效果: 实现步骤: 实现源代码: <template><div><el-form ref=&qu ...
- layui单选框verify_layui lay-verify form表单自定义验证规则详解
虽然layui的官方文档已经是写的比较详细,但是初次使用的时候总会懵一下,这里纪录一下lay-verify自定义验证规则的时候到底放哪. html: 提交 js: form.verify({ //数组 ...
- element UI 表单自定义验证,css水平且垂直居中方法
element UI 表单自定义验证 element UI提供了一种内部的表单验证,但是这种方法不能够来进行复杂的验证,如邮箱,手机号等的验证需要用到自定义验证 首先是element UI 提供的基础 ...
- element form表单提交数据之后清空所有输入框
element form表单提交数据之后清空所有输入框 首先el-form标签上的ref属性名和调方法名统一,还有要绑定所有表单数据的一个大对象就是 :model属性,然后prop属性绑定的值要和v- ...
- form表单动态设置enctype不生效问题
问题说明: 在一个form表单中需要发送两种enctype的请求,因此就需要对form表单的enctype进行动态修改.具体做法如下: 1.需要发送application/x-www-form-url ...
- 简易封装 element form表单
1.Form 表单 由输入框.选择器.单选框.多选框等控件组成,用以收集.校验.提交数据 典型表单 包括各种表单项,比如输入框.选择器.开关.单选框.多选框等. 在 Form 组 ...
- js中实现form表单动态提交
最近遇到了调用某银行支付功能的需求 需要使用form表单提交进行传参 记录一下 //创建表单var form = document.createElement("form");// ...
- IView的Form表单自定义验证需注意事项
写自定义验证时,除需要Form中的ref.rules.model和FormItem中的prop数据结构的高度对应外,还要注意,在绑定model中的对应prop之前,还需要清理ref中的fields.否 ...
- VUE element-ui之form表单自定义验证11位手机号码(封装验证规则)
步骤: 封装验证规则: export function isvalidPhone(phone) {const reg = /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2 ...
最新文章
- mysql 求数据的长度_mysql 如何求数据的长度
- python读取txt文件并写入excel-Python读取txt内容写入xls格式excel中的方法
- 人脸识别屡遭非议,会成为“潘多拉魔盒”吗?
- 利用python爬虫(part3)--正则表达式
- QT —— 应用程序发布
- python顺序结构代码_Python代码结构——顺序、分支、循环
- java+getactionmap_Struts2 使用OGNL遍历map方法详解
- 百度面试题:malloc/free 与 new/delete 的区别
- DSP之时钟与定时器之一时钟发生器
- webserver接口调用(一)
- 利用 JavaScript 快速切换正体中文和简体中文
- Cannot mix different versions of joi schemas错误
- 3Dmax自动加载脚本错误,语法错误:位于bad,需要因子
- Xcode8去除控制台多余打印
- 短信接口api发送-kewail
- 解析十大网络防骗术 全面防范网络欺诈
- 用计算机说出人说的话,用计算机语言说一句情话
- 数据挖掘人工神经网络,神经网络的数据处理
- 华为云桌面客户端_华为云服务器购买及环境搭建简述
- 什么是 Razor?
热门文章
- 山东农业大学考研计算机专业分数,山东农业大学研究生分数线
- 战争迷雾效果 第1章_要探索,不要地图全开!
- 决策树和随机森林预测员工离职率学习代码
- ​单页应用程序是如何打破网页设计的?
- AndroidQQ登录
- 使用SQLite打开本地.db文件
- android 自定义数字软键盘,(笔记)Android自定义数字键盘
- Leetcode799. 香槟塔
- python制作图表放入excel_python- xlsxwriter模块使用(拓展:Excel插入图表)
- 设置Button图片位置