el-table通过这样封装可以实现校验-表格校验的原理

我们一般在后台系统中,很常见的操作时表格里面嵌套表单,之前我的网上找到了一些封装的用法:

<el-form :model="formData" :rules="ruleData" ref="formDom"><el-table :data="formData.tableData"><el-table-columnv-for="item in column":key="item.prop":label="item.label"><template slot-scope="scope"><el-form-item:ref="'tableData.' + scope.$index + '.' + item.prop":prop="'tableData.' + scope.$index + '.' + item.prop":rules="ruleData[item.prop]"><el-inputv-model="scope.row[item.prop]"@change="handleChange(scope, item)"></el-input></el-form-item></template></el-table-column></el-table>
</el-form>// data中的数据
formData: {tableData: [{ name: "", age: "" },{ name: "", age: "" },{ name: "", age: "" },{ name: "", age: "" },],
},
ruleData: {name: { message: "请输入名字", required: true },age: { message: "请输入年龄", required: true },
},
column: [{ label: "名字", prop: "name" },{ label: "年龄", prop: "age" },
],

在这里我不太理解prop为什么要写成"'tableData.' + scope.$index + '.' + item.prop"这个样子就实现了校验的效果。后来在一次项目中偶然去查看了一下el-form的源码,才明白其中的道理;
在这里插入图片描述
首先我们看到el-form组件的文件路径是这样的,那么其实form-item是一个单独的组件,我们通过form -> form-item嵌套的时候,其实最后实现校验的过程是一个个去校验 form-item,form组件最终的校验:

// 最主要的核心功能
validate(callback){this.fields.forEach(field => {field.validate('', (message, field) => {if (message) {valid = false;}invalidFields = objectAssign({}, invalidFields, field);if (typeof callback === 'function' && ++count === this.fields.length) {callback(valid, invalidFields);}});
});
}

其中 this.fields就是el-form-item集合:

// el-form的created中
this.$on('el.form.addField', (field) => {if (field) {this.fields.push(field);}
});// el-form-item的mounted中
this.dispatch('ElForm', 'el.form.addField', [this]);// 内部自己使用 dispatch实现组件通讯

其中最主要的就是调用el-form-itemvalidate方法:

validate(trigger, callback = noop) {this.validateDisabled = false;const rules = this.getFilteredRule(trigger);if ((!rules || rules.length === 0) && this.required === undefined) {callback();return true;}this.validateState = 'validating';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);});}

其中主要的核心功能是单个的 rules(校验规则)model(数据)
rules的获取:

// 首先通过getFilteredRule方法过滤rules
getFilteredRule(trigger) {// 获取 rulesconst rules = this.getRules();return rules.filter(rule => {if (!rule.trigger || trigger === '') return true;if (Array.isArray(rule.trigger)) {return rule.trigger.indexOf(trigger) > -1;} else {return rule.trigger === trigger;}}).map(rule => objectAssign({}, rule));
},// getFilteredRule最核心的方式就是getRules
getRules() {// 这个就是我们在 el-form中传递的ruleslet formRules = this.form.rules;// 这个就是我们自己在 el-form-item传递的rulesconst selfRules = this.rules;// 这里判断是不是必输的const requiredRule = this.required !== undefined ? { required: !!this.required } : [];// 这里通过formRules结合prop获取最新的prop(其实是一个对象,里面有key,value比较重要的值)const prop = getPropByPath(formRules, this.prop || '');formRules = formRules ? (prop.o[this.prop || ''] || prop.v) : [];// 最终将rules做一个整合return [].concat(selfRules || formRules || []).concat(requiredRule);
},

最终我们通过分析发现其实去匹配 el-form中整体的rules是通过getPropByPath这个方法的:

function getPropByPath(obj, path) {let tempObj = obj;path = path.replace(/\[(\w+)\]/g, '.$1');path = path.replace(/^\./, '');let keyArr = path.split('.');let i = 0;for (let len = keyArr.length; i < len - 1; ++i) {let key = keyArr[i];if (key in tempObj) {tempObj = tempObj[key];} else {throw new Error('please transfer a valid prop path to form item!');}}return {o: tempObj,k: keyArr[i],v: tempObj[keyArr[i]]};
}

path.split('.')这里会对prop进行切割,我们最终得到的值其实是这样的:
在这里插入图片描述
最终通过formRules = formRules ? (prop.o[this.prop || ''] || prop.v) : [];formRules这个值变成了undefined
再返回validate方法里面,看model,通过这里model[this.prop] = this.fieldValue,我们来看fieldValue

function getPropByPath(obj, path) {// 这里的值其实一个对象数组:// { tableData: [// { name: "", age: "" },// { name: "", age: "" },// { name: "", age: "" },// { name: "", age: "" },
// ] },let tempObj = obj;path = path.replace(/\[(\w+)\]/g, '.$1');path = path.replace(/^\./, '');// 那第一个来说就是 tableData.0.namelet keyArr = path.split('.');let i = 0;for (let len = keyArr.length; i < len - 1; ++i) {// 不断的去匹配 tempObj 中的值let key = keyArr[i];if (key in tempObj) {tempObj = tempObj[key];} else {throw new Error('please transfer a valid prop path to form item!');}}return {o: tempObj,k: keyArr[i],v: tempObj[keyArr[i]]};
}
// 其实就是一个计算属性
fieldValue() {// 我们给 el-form传递的model值const model = this.form.model;if (!model || !this.prop) { return; }let path = this.prop;if (path.indexOf(':') !== -1) {path = path.replace(/:/, '.');}// 还是通过这个方法获取到对应的值return getPropByPath(model, path, true).v;
},

最终fieldValue就表示了表格组件中每个小块的值,通过 propmodel去匹配对应的值,和rules结合AsyncValidator实现表单校验。这里我们也可以看出给el-form传递model,给el-form-item传递proprules的重要性。
写到这里我还有一个疑问,那就是在getRules方法中,通过getPropByPath其实最终是把formRules转换成一个undefined的,那么是不是在此次封装中给el-form传递的rules没用了,其实真正起主导作用的还是给el-form-item传递的rules,那么把el-form-item中的rules删除掉是不是就校验不了了。通过验证证实了我的猜想。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498260.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5G提速工业物联网发展

对于普通消费者来说&#xff0c;5G的概念可能就是更快的网速&#xff0c;5G带来的上网体验提升是最直观的&#xff0c;因为拿手机可以实时观看高清晰度的视频&#xff0c;且无需太久的等待时间。 而更低的时延与更高的可靠性对C端用户带来的体验改善&#xff0c;相对来说就小很…

【Linux深入剖析】再续环境变量 | 进程地址空间

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1.环境变量再续1.1 和…

Linux Centos7配置SSH免密登录

Linux Centos7配置SSH免密登录 配置SSH免密登录说明&#xff1a; 分两步 第一步、给Server A生成密钥对 第二步、给Server B授权 生成密钥对之后&#xff0c;我们可以看看它保存的目录下的文件。 接下来我们就要把Server A&#xff08;10.1.1.74&#xff09;的公钥拷贝到Se…

Vuepress的使用

介绍 将markdown静态资源转换成html。 动态资源的转换还有很多&#xff0c;为什么要使用Vuepress&#xff1f; 目录分析 项目配置 详情 具体配置请看文档 插件配置 vuepress-theme-vdoing 主题插件 npm install vuepress-theme-vdoing -D先安装依赖配置主题 使用vuep…

八、ActiveMQ持久化

ActiveMQ持久化 一、MQ的高可用二、持久化介绍三、持久化存储方式1.AMQ Mesage Store(了解&#xff09;2.KahaDB消息存储(默认)2.1 存储原理 3.JDBC消息存储4.LevelDB消息存储(了解)5.JDBC Message Store with ActiveMQ Journal查询持久化存储方式 四、持久化存储使用1.JDBC消息…

Linux磁盘性能方法以及磁盘io性能分析

Linux磁盘性能方法以及磁盘io性能分析 1. fio压测1.1. 安装fio1.2. bs 4k iodepth 1&#xff1a;随机读/写测试&#xff0c;能反映硬盘的时延性能1.3. bs 128k iodepth 32&#xff1a;顺序读/写测试&#xff0c;能反映硬盘的吞吐性能 2. dd压测2.1. 测试纯写入性能2.2. 测试…

如何系统地学习Python:一份全面指南

在当前的技术环境中&#xff0c;Python已经成为了最受欢迎的编程语言之一。无论你是想进入数据科学领域&#xff0c;开发网站&#xff0c;还是简单地想提高工作效率&#xff0c;学习Python都是一个明智的选择。本文将为你提供一个系统学习Python的详细指南&#xff0c;包括理论…

Keepalived 双机热备基础知识

7.1 Keepalived 双机热备基础知识 Keepalived起初是专门针对LVS设计的一款强大的辅助工具&#xff0c;主要用来提供故障切换(Failover) 和健康检查査(Health Checking)功能一一判断LVS 负载调度器、节点服务器的可用性&#xff0c;及时隔离并替 换为新的服务器&#xff0c;当故…

【文生视频】Diffusion Transformer:OpenAI Sora 原理、Stable Diffusion 3 同源技术

文生视频 Diffusion Transformer&#xff1a;Sora 核心架构、Stable Diffusion 3 同源技术 Sora 网络结构提出背景输入输出生成流程变换器的引入Diffusion Transformer (DiT)架构Diffusion Transformer (DiT)总结 OpenAI Sora 设计思路阶段1: 数据准备和预处理阶段2: 架构设计阶…

从0到1实现五子棋游戏!!

Hello&#xff0c;好久不见宝子们&#xff0c;今天来给大家更一个五子棋的程序~ 我们今天要讲的内容如下&#xff1a; 文章目录 1.五子棋游戏介绍1.1 游戏玩法介绍&#xff1a; 2.准备工作2.1 具体操作流程 3.游戏程序主函数4.初始化棋盘4.1.定义宏变量4.2 初始化棋盘 5.打印…

从尺寸到实用性,教你如何设计理想电脑桌。福州中宅装饰,福州装修

设计卧室书桌&电脑桌时&#xff0c;需要考虑多个方面和注意事项&#xff0c;以确保书桌既实用又舒适。以下是一些关于卧室书桌&电脑桌设计的建议&#xff1a; ❶书桌&电脑桌的尺寸 根据卧室的空间大小和个人需求&#xff0c;确定合适的书桌尺寸。一般来说&#xf…

back-side illumination (BSI)

目录 原理学习资料 原理 这个术语有点误导作用&#xff0c;其实是把先前的在上面的层放在了后面&#xff0c;后面的层放在了前面。 以前的制造工艺是金属布线放在了前面&#xff0c;会挡住部分光线&#xff0c;以前的像素点比较大&#xff0c;没什么问题&#xff0c;后来像素…