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.mzph.cn/news/708791.shtml

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

相关文章

美易全球投资中心:美股涨势倦怠,要预测顶部位置是不可能的

在过去的几个月里&#xff0c;美股市场一直处于涨势&#xff0c;但近期这种涨势似乎已经开始倦怠。高盛的分析师表示&#xff0c;尽管市场可能会出现波动&#xff0c;但目前没有明显的抛售诱因。他们也指出&#xff0c;预测市场的顶部位置是非常困难的&#xff0c;因为市场走势…

k8s pod理论

一、Pod概述 1、Pod的定义 Pod是K8S中创建和管理的最小单位。 2、一个Pod至少包含多少容器 1个pause容器&#xff08;基础容器/父容器/根容器&#xff09;和 1个或者多个应用容器&#xff08;业务容器&#xff09; 通常一个Pod最好只包含一个应用容器&#xff0c;一个应用容…

找不到FeignClient Bean对象的解决方法(两个)

当我们自己在编写独立的模块过着jar包的时候&#xff0c;在另外一个模块引用到这个依赖&#xff0c;若像是本例中的UserClient&#xff0c;是需要注入成Bean才能成功注入到Spring的IO容器中&#xff0c;从而成功调用。下面有两个解决方法&#xff1a; 问题&#xff1a; UserCl…

基于Redisson,实现分布式锁注解

1.原始写法 我们平常使用redisson的分布式锁是不是基本都用下面的这个模板&#xff0c;既然是模板&#xff0c;那为何不把他抽出来呢&#xff1f; // 尝试加锁&#xff0c;最多等待100秒&#xff0c;上锁以后10秒自动解锁 boolean res lock.tryLock(100, 10, TimeUnit.SECON…

华为OD技术面试案例5-2024年

背景 985本计算机专业&#xff0c;目标院校。 1.15 投递 在某BOSS上投递的简历&#xff0c;HR人很nice&#xff0c;非常负责任。 1.19 收到机试通知 第一题是一个哈夫曼编码&#xff0c;第三题是一个动态规划&#xff0c;机试整体难度不算高&#xff0c;刷leetcode hot100…

PTA——L2-016 愿天下有情人都是失散多年的兄妹(dfs)

文章目录 一、题目二、题解1.基本思路&#xff1a;2.代码&#xff1a; 一、题目 L2-016 愿天下有情人都是失散多年的兄妹 分数 25 全屏浏览 作者 陈越 单位 浙江大学 呵呵。大家都知道五服以内不得通婚&#xff0c;即两个人最近的共同祖先如果在五代以内&#xff08;即本人、…

react + umi中如何使用rem完成自适应布局

只要写css就可以实现&#xff1a;flex rem布局&#xff1b; 在项目的global.less中根据媒体查询&#xff1b; 媒体查询是用于根据设备的特性&#xff08;如屏幕尺寸、屏幕方向、分辨率等&#xff09;来应用不同的 CSS 样式的技术。以下是一些常用的媒体查询尺寸&#xff1a; 小…

WordPress分类目录ID怎么看?如何查找WordPress标签ID?

在WordPress网站中&#xff0c;我们需要判断某篇文章是否属于某个分类目录&#xff0c;或者是否拥有某个标签&#xff0c;那么就需要用到分类目录ID和标签ID&#xff0c;那么WordPress分类目录ID怎么看&#xff1f;如何查找WordPress标签ID&#xff1f;下面boke112百科就跟大家…

五、生成数字列表

输入描述&#xff1a; 输入一行整数&#xff0c;数字之间以空格间隔。 输出描述&#xff1a; 输出这些数字组成的完整列表。 示例1 输入&#xff1a; 1 2 3 4 5 复制输出&#xff1a; [1, 2, 3, 4, 5] numinput() list_strnum.split() int_list[int(i) for i in list_str…

Node.js基础---加载机制

模块的加载机制 1. 优先成缓存中加载 模块在第一次加载后会被缓存&#xff0c;意味着多次调用 require() 不会导致模块代码被多次执行 注意&#xff1a;无论是什么模块都会优先从缓存内加载&#xff0c;以提高加载效率 2. 内置模块的加载机制 内置模块是 Node.js官网提供的模块…

数据结构·顺序表实现通讯录

目录 1 基本格式 2 结构体的声明 3 初始化 销毁 扩容 插入 删除 4 增加联系人 5 查看通讯录 6 删除联系人 7 查找联系人 8 修改联系人 9 整体代码 引言&#xff1a; 有了前面顺序表的基础&#xff0c;我们可以尝试利用顺序表实现通讯录&#xff0c;日常使用中&#x…

【论文阅读】微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述

Micro and nanobubbles technologies as a new horizon for CO2-EOR and CO2 geological storage techniques: A review 微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向&#xff1a;综述 期刊信息&#xff1a;Fuel 2023 期刊级别&#xff1a;EI检索 SCI升级版工程技术1区…

【LeetCode-简单】69.x的平方根 + 367.有效的完全平方数 - 二分法

力扣题目链接 给定非负整数x&#xff0c;求x的算数平方根&#xff08;只保留整数部分&#xff09; 这个问题可以看成在区间 [0, x) 中寻找一个整数 target 使得 target * target 趋近于x 采用二分法&#xff0c;排除0与1这两个特殊情况后&#xff08;不排除则left 0, right…

Python实现时间序列分析进行平稳性检验(ADF和KPSS)和差分去趋势(adfuller和kpss算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中的平稳性检验是评估一个时间序列是否具有稳定的均值和方差。在经济学、金融学以及其他诸…

麒麟OS:操作系统国家队

这是ren_dong的第31篇原创 1、中标软件 中标软件&#xff1a;国产操作系统龙头 中标软件有限公司成立于2003 年&#xff0c;是国产自主操作系统和办公软件产品提供商&#xff0c;拥有 国防、民用两方面的相关企业与产品资质&#xff0c;是安全操作系统旗舰企业。 中标软件的主要…

飞天使-学以致用-devops知识点3-安装jenkins

文章目录 构建带maven环境的jenkins 镜像安装jenkinsjenkins yaml 文件安装插件jenkins 配置k8s创建用户凭证 构建带maven环境的jenkins 镜像 # 构建带 maven 环境的 jenkins 镜像 docker build -t 192.168.113.122:8858/library/jenkins-maven:jdk-11 .# 登录 harbor docker …

解读人工智能的理论基石

1956年的一个夏天&#xff0c;在达特茅斯学院的一个小会议室里&#xff0c;一群充满好奇和野心的年轻科学家聚集在一起&#xff0c;他们有一个共同的梦想&#xff1a;创造能够模仿人类智能的机器。这不仅仅是科幻小说的情节&#xff0c;更是人工智能历史上一个真实的起点。从那…

基于JAVA的毕业生追踪系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登陆注册模块2.2 学生基本配置模块2.3 就业状况模块2.4 学历深造模块2.5 信息汇总分析模块2.6 校友论坛模块 三、系统设计3.1 用例设计3.2 实体设计 四、系统展示五、核心代码5.1 查询我的就业状况5.2 初始化就业状况5.…

防御保护:防火墙内容安全

一、IAE&#xff08;Intelligent Awareness Engine&#xff09;引擎 二、深度检测技术(DFI和DPI&#xff09; 1.DPI – 深度包检测技术 DPI主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#xff09;&#xff0c;之后对数据包的内容进行识别。&#x…

微服务 人工智能AI 物联网智慧工地云平台源码

目录 ​编辑 智慧工地架构 智慧工地系统 智慧工地云平台功能模块 1、基础数据管理 2、考勤管理 3、安全隐患管理 4、视频监控 5、塔吊监控 6、升降机监控 7、移动端数据推送 智慧工地管理平台子系统构成 智慧工地物联网解决方案&#xff0c;对工地施工安全人员、设…