深入了解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]);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
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 change
this.fields.forEach(field => {
field.removeValidateEvents();
field.addValidateEvents();
});
if (this.validateOnRuleChange) {
this.validate(() => {});
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 最后看
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);
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
从上面的第一点中可以看到,因为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)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
总结
终须由浅入深,浮于表面便是管中窥豹,自身还需静下心认真研究
深入了解Element Form表单动态验证问题 转载的更多相关文章
- Vue Element Form表单时间验证控件使用
如果直接使用Element做时间选择器,其规则(rules)不添加type:'date',会提示类型错误,处理这个需要规范值的类型为date. 时间格式化过滤器 import Vue from 'vu ...
- Element Form表单实践(下)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...
- Element Form表单实践(上)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...
- Element form表单方法resetFields无效
之前遇到resetFields无效时都是自己手动用this.ruleForm = Object.assign({}, this.ruleForm, this.$options.data().ruleF ...
- 重写form 表单的验证信息
(function($) { var isformValidationPostBack=true; var isformValidation = false; $.extend({ formValid ...
- form 表单jquery验证插件使用
第一部分:表单样式 <form action="#" method="post" id="regist"> <tabl ...
- a链接易混淆与form表单简易验证用法详解
链接可以说遍布互联网,比如你想提供一个可以跳转到百度首页的链接给网友,那么代码如下: <a href="http://www.baidu.com">百度一下,你就知道& ...
- WTForms 表单动态验证
class UserDetails(Form): group_id = SelectField(u'Group', coerce=int) def edit_user(request, id): us ...
- form表单点击后验证
function check(){ var customertype = document.getElementById("customertype"); //alert(cust ...
随机推荐
- EDP转LVDS屏转接板方案|基于INTELX86主板和商显应用EDP转LVDS设计CS5211
众所周知LVDS接口是美国NS美国国家半导体公司为克服以TTL电平方式传输宽带高码率数据时功耗大,电磁干扰大等缺点而研制的一种数字视频信号传输方式.由于其采用低压和低电流驱动方式,实现了低噪声和低功耗 ...
- Java EE数据持久化框架笔记 • 【目录】
章节 内容 实践练习 Java EE数据持久化框架作业目录(作业笔记) 第1章 Java EE数据持久化框架笔记 • [第1章 MyBatis入门] 第2章 Java EE数据持久化框架笔记 • [第 ...
- HTML5 +Java基础 大一结业认证考试试题 - 云南农业职业技术学院 - 互联网技术学院 - 美和易思校企合作专业
第1题 [单选题][0.33分][概念理解] 关于java中的逻辑运算符,下列说法正确的是 逻辑运算符||.&&.!都是用于连接两个关系表达式</p> 当&&am ...
- MySQL数据操作与查询笔记 • 【目录】
持续更新中- 我的大学笔记>>> 章节 内容 第1章 MySQL数据操作与查询笔记 • [第1章 MySQL数据库基础] 第2章 MySQL数据操作与查询笔记 • [第2章 表结构管 ...
- Java如何打好牢固的基础?
如果纯粹是为了学Java,那么不建议阅读本文,因为本文不是从理论和教科书的角度讲述如何打好java基础,而是会从"快速用java挣钱"这个角度,讲边学.边做项目和边提升的方法. 在 ...
- [Blue Prism] Data item 的使用
1.用于存储各种数据类型的变量,支持的数据类型如下: Binary - 用于存储二进制 blob,例如文本文件. Date - 用于存储日期. 此数据类型与 DateTime 类似,只是 Date ...
- Python_jsonPath模块的使用
jsonpath简介 如果有一个多层嵌套的复杂字典,想要根据key批量提取value,还是比较繁琐的.jsonPath模块就能解决这个痛点,接下来我们来学习一下jsonpath模块. 因为jsonpa ...
- 禁止yum update 自动更新系统内核
使用yum update更新系统软件时,禁止升级内核,可以防止产生因不兼容导致的未知错误. 设置前请先备份原设置文件yum.conf cp /etc/yum.conf /etc/yum.conf ...
- mysql-5.7.20-winx64安装图解教程
原文链接:https://www.toutiao.com/i6494052843912167949/ 将安装包解压 解压目录 鼠标右键"我的电脑",弹出"快捷菜单&quo ...
- 学习笔记--我的第一个Java程序
我的第一个Java程序 // pubilc 表示公开的 // class 表示定义一个类 // HelloWorld 表示一个类名 public class HelloWorld { // 表示定义一 ...