asp.net接受表单验证格式后再提交数据_如何解析 el-form-renderer 表单渲染器1.14.0...

df998c499c3b54962605c53059672646.png

b496fd11a1164ef94fe44882f3500829.png

DEEPEXI 大前端

常人道,一入开发深似海,技术学习无止境。在新技术层出不穷的前端开发领域,有一群身怀绝技的开发,他们在钻研前沿技术的同时,也不忘分享他们的成果,回馈社区。下面,就由小水滴带大家看一下滴普大前端对新版 el-form-renderer 表单渲染器的硬核解析吧~

DEEPEXI 官方:产品介绍与技术分享

https://www.zhihu.com/org/deepexi

DEEPEXI 大前端:前端技术成果的分享

https://zhuanlan.zhihu.com/deepexi-frontend

开源地址(欢迎点击github来贡献你的star哦 ✨)

https://github.com/deepexihttps://github.com/FEMessage

el-form-renderer与表单

表单面临的难题

表单本质上是什么?表单用来承载业务需求的交互逻辑,表单的最终目的是提交一些特定格式的数据。

但在日常工作中,公司的业务不会停下,需求必然要跟着业务而不断演化,一个看似简单的页面表单也会变得越来越臃肿。

表单变得难以维护

拿项目交接举例子。项目交接了N手,各人都按各自的风格写代码;产品也交接了好几手,各按各的套路提需求。根本原因是代码的维护成本与业务不断变化之间的矛盾。

当表单中出现联动的需求,或者跨行之间发生制约关系时,表单代码的复杂度就会上升。随着业务需求的演变,如果代码处理的不好,会变得越来越难维护。

为什么要用el-form-renderer

el-form-renderer是基于 element-ui 封装的表单渲染器,但不局限于 element-ui 组件。

在完整继承了 element 的form表单属性的基础上进行了简单扩展,一些非表单组件或者封装的自定义组件,如图片上传、富文本等也可进行整合,从而用户能够通过使用一段预设的数据渲染出一个完整的表单。

用一句话来概括,el-form-renderer 让表单的构建与维护变得更简单了。

el-form-renderer(表单渲染组件)

ad3409bb6212ea6eaa4179165ce37793.png

issues:

a271eac5aaad247d01371a8434ae7277.png

el-form-renderer 1.14.0 重磅发布

el-form-renderer 1.14.0 : 支持 v-model

版本更新主要带来了 v-model 功能,并加入了 cypress 做 e2e 测试来护航。下面一起来看看开发小哥此时版本迭代的心路历程吧~

功能:v-model

这次 feature 版本更新,主要是为了 v-model 功能开展的。其可以解决以下问题:

  • 不再需要对 ref 操作 updateForm、getFormValue 来与数据交互。
  • 可以直接观察当前的表单数据变更,来进行特定操作。

后续对 valid 状态,也通过 prop + sync 的形式管理,基本就可以脱离对 ref 的依赖。

提升代码质量

由于 el-form-renderer 已经是历时两年多的开源项目,许多代码经多人转手,已经存在以下问题:

  • 不合适的写法。比如大量使用 render 函数;
  • 大量使用 mixin 和字符串拼接来调用功能,开发者难以定位调用链条。比如在生成 option 数组时;
  • 废弃的功能。比如不太好用的 enableWhen 等等;
  • 没有注释的 hack。比如尝试兼容 select, radio & checkbox 用法的代码(在1.14.1版本修复)。

所以提高维护性也是本次迭代的重中之重。开发从此开始。

测试

第一步,加入自动化测试。先前,项目中已经引入了 jest 做单元测试。单元测试可以保证一些核心逻辑的稳定性,比如一些数据处理、转换函数的输入输出意图。

但是其没有办法测试真实示例使用起来时的稳定性,比如用户真正在表单中输入值、点击重置按钮的行为。

此前,行为的稳定性只能依赖开发者和 review 人员手动对示例进行测试。

现在,项目使用 cypress 来对每个示例的行为进行自动化测试。这样开发者可以放心重构和添加功能,同时轻松维护过往表现的一致性。

如何写行为测试

重点应当关注用户行为层面,而不是代码输出层面。

比如,应当测试:

  • 用户输入文本。
  • 确认文本框中有该内容。
  • 用户点击提交按钮。
  • 确认窗口内显示成功信息。

而不是:

  • 用户点击按钮。
  • 等待某个接口有返回内容(测试按钮有没绑定到函数,和接口是否正常)。

重构

重构的主要成果是:

  • 用 template 重构了所以 render 函数。代码更符合 vue 规范写法。
  • 移除了 mixin。将相关功能转化成纯函数,并补充单元测试用例。
  • 层级调整。vue 组件移到 components 目录下;js 文件移到 util 目录下。
  • 优化函数命名。比如使用具体的 removeDollarInKey 替代 transformItem。
  • 梳理了关键复杂点的逻辑,并提取成纯函数,补充单元测试。
  • 补全了所有关键示例的端测试。
其中补充的单元测试包括:transformInputFormat(用 inputFormat 处理初始和 updateForm 的值);transformOutputFormat (用 outputFormat 处理 getFormValue 的值);collect (从 content 中搜集 options 和初始 value。

inputFormat & outputFormat

这次重构的最大难点,就是处理 inputFormat、 outputFormat、group 与表单值 value 的逻辑。直接给出定义的话:

  • 每个表单项的 inputFormat 接受当前 这一层(group) 的值,返回 当前项的值。
  • 每个表单项的 outputFormat 接受 当前项的值 ,返回的值先判断是不是对象:
    • 如果不是,返回值视作 当前项的值。
    • 如果是,返回值将整体覆盖到 这一层(group) 的值。

具体看如下示例。使用到的同学请务必注意其用法。

inputFormat

重构前:

/ content 配置
{id: 'a',inputFormat: v => v + 1 // 接受传入值,返回新值
}
//
this.$refs.form.updateForm({a: 1})
this.$refs.form.getFormValue() // {a: 2}

重构后:

// content 配置
{id: 'a',inputFormat: formValue => formValue.notA // 接受整个 formValue 来处理!
}
//
this.$refs.form.updateForm({notA: 1})
this.$refs.form.getFormValue() // {a: 1}

outputFormat

重构前:

// content 配置
[{id: 'a',default: 1,outputFormat: a => a + 1 // 接受内部值,返回处理过的值},{id: 'b',default: {c: 2},outputFormat: b => (b.c += 1, b)},
]
//
this.$refs.form.getFormValue() // {a: 2, b: {c: 3}}

重构后:

// content 配置
[{id: 'a',default: 1,outputFormat: a => a + 1 // 这个的理解是对的},{id: 'b',default: {c: 2},outputFormat: b => (b.c += 1, b) // 当返回值是对象时,会整体覆盖到上一层!},
]
//
this.$refs.form.getFormValue() // {a: 2, c: 3}

开发功能:v-model

开发过程

  • 新增属性 form,作为对外 v-model 的属性。
  • 在 watch 里对接数据流水线:
    • 监听 form、content 的变更 -> 搜集初始值 --inputFormat--> value
    • 监听 value 的变更 --outputFormat--> form
  • 写新的示例 v-model.md 和测试 v-model.spec.js(参考 basic 即可)。

测试流程

  • 输入各种 input、select、radio。
  • 检查输入后 v-model 的状态。
  • 点击 reset 按钮,v-model 回到初始状态。

发现问题

  • 在模拟点击 reset 按钮时,当 cypress 测试里点击重置按钮, reset 未生效。
  • 手动在 cypress 的调试浏览器中点击按钮,reset 生效。
  • 在普通浏览器中点击按钮,reset 生效 。
  • 在 reset 函数里打点,此时 reset 函数在以上情况中 都有被正常调用。
  • 尝试在 cypress 代码中先等待1秒再点击按钮,reset 未生效。
  • 尝试在 cypress 代码中连续写两次 click 按钮操作,reset 生效。
发现有可能是 cypress 的问题,标明注释说明手动测试成功,连点两次是 hack 写法。

解决问题

review 了下原本的 resetFields 逻辑,发现了如下问题

  • reset 后 el-select 报错的 bug。
  • reset 后,value 监听器监听不到改变,因为 el-form 的实现机制中改了 value 后没有 emit input 事件。
  • 如果在监听器上加 deep: true,则会发现新值和旧值相同。原因暂时不明。

在发现以上问题基础上,对代码进行如下修改

  • 在 form、value 监听器中用 lodash 的 isequal 判断前后的值,有变更时才 emit input 事件。
  • 参考 el-form 机制在内部实现了 resetFields:用的是 mounted 时传入的值,然后清除校验错误信息。

解决了用例异常的问题,有如下总结

  • 仍没有弄清楚为什么 cypress 的模拟操作代码调用的 resetFields 没有正常运作。
  • 疑似 cypress 的问题导致 resetFields 的其他问题被发现。
  • 重视测试的心以一种特别的方式让组件得到了回报。

关于初始状态

值得一提的是,目前 resetFields 所认定的 初始状态,是在组件 mounted 阶段时 v-model 的值。这点与 element 一致,因为一些 element 表单组件,会在 created 阶段,在传入的 value 值不合法时会重新 emit 一个正确的初始值给到 v-model。比如:

  • 开启了 multiple 的 el-select,会修正初始值为 [] 。
  • el-checkbox,会修正初始值为 [] (由 el-form-renderer 实现,原生是没有的)。

更新文档

此次更新顺带修复了一些老示例的错误用法。可能不少 el-form-renderer 的用户还不了解,el-form-renderer 的 disabled 属性,统一在配置最上层级设置:

// content 定义
[{disabled: true, // 在这里设置el: {disabled: true // 无效}}
]

意外之喜

文档:https://femessage.github.io/el-form-renderer/#/Demo/content

在写 v-model 数据流水线时,因为把 content 也融入在其中,所以现在可以在运行时修改 content,并观测表单变化。

快速咨询

登陆下方链接申请售前咨询,联系人姓名中加上推荐码 deepexi@zhihu 将有专人联系开通。

全场景数据智能引擎​cloud.deepexi.com

往期推荐

全渠道数字化营销平台 DEEPEXI DM​mp.weixin.qq.com
2eabda5ca1496fb58f9b2f51da0d446b.png
企业级研发效能利器 DEEPEXI DevOps​mp.weixin.qq.com
e2f3e3e19dd8c254036247f5eaafb909.png
企业级前端全链路开发服务平台:DEEPEXI Serverless(A20)​mp.weixin.qq.com
1f0d2af4cee87245dbdfac83b034dbb3.png
周期购自动派单率不高?可能是你不知道这个解决方案!​mp.weixin.qq.com
4b59e48f27113478382124267b1b35d1.png

更多内容

全场景数据智能引擎​cloud.deepexi.com
DEEPEXI是滴普科技公司面向企业数字化领域打造的云原生智能平台,定位于企业数字化引擎,为企业提供数字化全栈解决方案。滴普科技致力于互联网/大数据/人工智能/物联网领先技术产品解决方案的研发和实施,是领先的全场景数据智能服务商。

cbbcc4c95459a97b51c50fa8c1d16c43.png

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

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

相关文章

LeetCode 1751. 最多可以参加的会议数目 II(DP + 二分查找)

文章目录1. 题目2. 解题1. 题目 给你一个 events 数组,其中 events[i] [startDayi, endDayi, valuei] ,表示第 i 个会议在 startDayi 天开始,第 endDayi 天结束,如果你参加这个会议,你能得到价值 valuei 。 同时给你…

LeetCode 992. K 个不同整数的子数组(双指针)

文章目录1. 题目2. 解题1. 题目 给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定独立的子数组为好子数组。 (例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2&a…

压缩可以卸载吗_番禺街坊注意!微信发送高清大文件不压缩,网友:QQ可以卸载了?...

刚上新了表情包的微信又双叒叕出新功能了这次的功能有点实用昨天,腾讯微信团队宣布微信已支持向朋友发送高清视频和图片且不会被压缩微信用户点击对话框右下角的号右滑点击文件在上方选择手机相册就能选择用户想要发送的视频和图片了目前通过「文件」方式发送的内容…

LeetCode 1755. 最接近目标值的子序列和(状态枚举 + 双指针)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 nums 和一个目标值 goal 。 你需要从 nums 中选出一个子序列,使子序列元素总和最接近 goal 。 也就是说,如果子序列元素和为 sum ,你需要 最小化绝对差 abs(sum - goal) 。 返回 abs(sum …

路由器距离向量算法计算举例_路由器基本原理是什么 路由器基本发展情况介绍【图文】...

PLC路由器原理和ARR路由器基本原理要实现网络中通信节点彼此之间的通信,首先必须给每个节点分配一个唯一的IP地址。路由器应该至少有两个网络端口,分别连接LAN或者WAN子网上,每个端口必须具有一个唯一的IP地址,并且要求与所连接IP…

LintCode MySQL 1918. 第二高的球员的身高

文章目录1. 题目2. 解题1. 题目 编写一个 SQL 语句,获取球员 (players) 表中第二高的身高 (height) 表定义: players (球员表) https://www.lintcode.com/problem/1918 2. 解题 if(a,b,c), a true,执行 b, 否则 c -- Write your SQL Que…

python中使用opencv_如何在Python中使用OpenCV Stitcher类?

你正确使用它,因为某些原因导致进程失败. 结果元组的第一个值是错误代码,0表示成功.这里你得到1,这意味着,根据stitching.hpp,这个过程需要更多的图像. enum Status { OK 0, ERR_NEED_MORE_IMGS 1, ERR_HOMOGRAPHY_EST_FAIL 2, ERR_CAMERA_PARAMS_ADJUST_FAIL 3 }; ERR_NEE…

《高可用MySQL》2 – 单机版MySQL主从配置

这里搭建的主从是最简单的单一主从复制(即一个Master和一个slave,没有任何的热机备份和多slave),该主从结构的基本拓扑图如下所示: 建立基本的主从复制可以总结为以下三个基本步骤: 配置master服务器配置sl…

LintCode MySQL 1936. 张三的故事 III

文章目录1. 题目2. 解题1. 题目 记者调查发现,张三所在学校还有一金牌教师,其所带的学生毕业后人均知名学府。 记者对该老师所教的学生的情况产生了好奇。 students 表中记录了学生的姓名以及班级 (class_id),classes 表中记录了班级的名称以…

语言4位bcd码怎么加加_S7300400如何使用SCL语言调用SFC1(READ_CLK)读取日期和时间?...

系统功能 SFC1 用于读取 CPU 的系统时钟。系统时钟存储在数据类型为DATE_AND_TIME的变量里。通过指针访问系统时钟的单个组成元素。数据类型DATE_AND_TIME所包含的关于年、月、日、时等信息是以 BCD 码的格式存储在 8 个字节里。该数据类型显示的范围是:DT#1990-1-1…

LintCode MySQL 1932/1933. 挂科最多的同学 I / II

文章目录1. 题目2. 解题1. 题目 exams 表中存放着同学们的考试记录 请用 SQL 语句,找到挂科数最多的同学所对应的 student_id https://www.lintcode.com/problem/1932 2. 解题 -- Write your SQL Query here -- -- example: SELECT * FROM XX_TABLE WHERE XXX…

python 画三角函数_python,将三角函数绘制成二维数组

看起来a, b, c是常量&#xff0c;z是a和{}之间的np.linspace。在a 1 b 2 c 3 def triangle (z, a a, b b, c c): y np.zeros(z.shape) y[z < a] 0 y[z > c] 0 first_half np.logical_and(a < z, z < b) y[first_half] (z[first_half]-a) / (b-a) second…

LeetCode 1758. 生成交替二进制字符串的最少操作数(DP)

文章目录1. 题目2. 解题1. 题目 给你一个仅由字符 ‘0’ 和 ‘1’ 组成的字符串 s 。 一步操作中&#xff0c;你可以将任一 ‘0’ 变成 ‘1’ &#xff0c;或者将 ‘1’ 变成 ‘0’ 。 交替字符串 定义为&#xff1a;如果字符串中不存在相邻两个字符相等的情况&#xff0c;那…

python内置的集成开发工具是什么_python内置的集成开发工具是什么_后端开发

go语言之goroute协程_后端开发 协程&#xff08;coroutine&#xff09;是Go语言中的轻量级线程实现&#xff0c;由Go运行时&#xff08;runtime&#xff09;管理。下面就来由go入门教程栏目介绍一下go语言中的goroute协程。python内置的集成开发工具是什么 Python自带的集成开发…

SQL Server 2008R2数据库文件导入到SQL Server 2008数据库中

最近&#xff0c;电脑重装系统之后&#xff0c;安装了SQL Server 2008。附加数据库文件的时候&#xff0c;发现无法附加&#xff0c;提示版本不对。想起来&#xff0c;原来的数据库版本是SQL Server 2008R2。低版本的数据库管理工具无法兼容高版本的数据库文件&#xff0c;所以…

python语言的注释语句引导符_Python 为什么用 # 号作注释符?

关于编程语言中的注释&#xff0c;其重要性基本上已为大家所共识。 然而关于注释的规范&#xff0c;这个话题就像我们之前聊过的缩进、终止符和命名方式一样&#xff0c;众口难调。 注释符通常可分为两种&#xff0c;即行注释与块注释&#xff08;inline/block&#xff09;&…

python 白化_MeteoInfo和Python显著性检验

MeteoInfo显著性检验&#xff1a;MeteoInfo官网&#xff1a;http://www.meteothink.org源代码&#xff1a;https://github.com/meteoinfofn F:/RMeteoInfo/data/test.txtny 71nx 144m ny * nxn 62ss1 asciiread(fn, shape(71,144,n))ss1 ss1[::-1,::1,:]X ss1.reshape(…

LeetCode 1760. 袋子里最少数目的球(二分查找)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 nums &#xff0c;其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations 。 你可以进行如下操作至多 maxOperations 次&#xff1a; 选择任意一个袋子&#xff0c;并将袋子里的球分到 2 个新的袋子中&a…

判断鼠标不在控件上_VB常用控件属性讲解单选按钮、复选框总结

1单选按钮、复选框做为VB编程中的选择性控件&#xff0c;在实际程序中有着广泛的应用&#xff0c;所以熟练掌握其特殊属性的用法就很重要了&#xff01;单选按钮、复选框的实际应用图复选框(CheckBox)控件属性说明Name复选框控件的名称Alignment设置标题文本的对齐方式, 取值为…

LeetCode 1763. 最长的美好子字符串

文章目录1. 题目2. 解题1. 题目 当一个字符串 s 包含的每一种字母的大写和小写形式 同时 出现在 s 中&#xff0c;就称这个字符串 s 是 美好 字符串。 比方说&#xff0c;"abABB" 是美好字符串&#xff0c;因为 ‘A’ 和 ‘a’ 同时出现了&#xff0c;且 ‘B’ 和 ‘…