asp.net接受表单验证格式后再提交数据_看滴普科技大前端如何玩转el-form-renderer 表单渲染器1.14.0

0c24e806228b4120b18e82f61fdbace2

DEEPEXI 大前端

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

aa494de5c1634fec81a4b5fc8a49e75e

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

el-form-renderer与表单

表单面临的难题

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

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

表单变得难以维护

拿项目交接举例子。项目交接了N手,各人都按各自的风格写代码;产品也交接了好几手,各按各的套路提需求。根本原因是代码的维护成本与业务不断变化之间的矛盾。当表单中出现联动的需求,或者跨行之间发生制约关系时,表单代码的复杂度就会上升。随着业务需求的演变,如果代码处理的不好,会变得越来越难维护。

为什么要用el-form-renderer

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

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

4be135a5a5c24a458bf8dc5ecfbf429a

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

94b7f5ec41de4b32b58522db10f26e3f

issues

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 // 无效}}]

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

结语

el-form-renderer 虽然一路遭遇到吐槽很多,但更多的是忠实粉丝们孜孜不倦地为其提交代码。直到今天,可以看到其相对于原生 element,开发体验已经有了长足的进步。现在有了端对端测试,开发和维护功能更是如虎添翼。这里感谢已为开源作出贡献的开发者们,也欢迎更多小伙伴加入我们 DEEPEXI 开源生态中哦~

“作家不靠灵感写字✍️”

作者:沈扬东

更多内容请点击左下方“了解更多”

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

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

相关文章

测试用例设计方法_黑盒测试——测试用例设计方法

黑盒测试也称为功能测试或数据驱动测试。通过软件的外部表现来发现其缺陷和错误。在测试时,把被测程序视为一个不能打开的盒子,在完全不考虑程序内部逻辑结构和内部特性的情况下进行。它是在已知产品所应具有的功能前提下,通过测试来检测每个…

SpringAop @Pointcut(“@annotation“)\@Aspect练习

切面记录日志 切面类 Slf4j Aspect Component public class AspectForFeign {Pointcut("execution(public * com.keke.remote..*Feign.*(..))")public void pointcut() {}Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) thro…

Mybatis缓存机制详解与实例分析

前言: 本篇文章主要讲解Mybatis缓存机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了😁 以下正文开始 Mybat…

delphi语言转为汇编语言_每天5分钟,轻松建立技术图谱 编程语言黑历史

阿T课堂开播啦!这里只有干货干锅,没有水坑没有套路!计算机编程语言的发展,也是随着计算机本身发展而发展。人类不断的提高科技的同时,也必须使工具的使用越来越简化,从而提高整个社会效率,这其中…

水系图一般在哪里找得到_进展 | 水系钠离子电池研究取得重要进展

水系钠离子电池兼具钠资源储量丰富和水系电解液本质安全的双重优势被视为一种理想的大规模静态储能技术。此前,我们针对这水系钠离子电池体系做了一些探索(Nature Communications 2015, 6, 6401;Advanced Energy Materials 2015, 5, 1501005;…

@Around简单使用示例——SpringAOP增强处理

Around的作用 既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作;可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;可以改变执行目标方法的参数值,也…

python numpy逆_Python使用numpy计算矩阵特征值、特征向量与逆矩阵

原标题:Python使用numpy计算矩阵特征值、特征向量与逆矩阵 Python扩展库numpy.linalg的eig()函数可以用来计算矩阵的特征值与特征向量,而numpy.linalg.inv()函数用来计算可逆矩阵的逆矩阵。 >>> importnumpy as np >>> x np.matrix([…

Mysql索引数据结构有多个选择,为什么一定要是B+树呢?_面试 (MySQL 索引为啥要选择 B+ 树)

Mysql索引数据结构 下面列举了常见的数据结构 二叉树红黑树Hash表B-Tree(B树) Select * from t where t.col5我们在执行一条查询的Sql语句时候,在数据量比较大又不加索引的情况下,逐行查询并进行比对,每次需要从磁盘…

一篇搞懂mysql中的索引(大白话版)

容易来说,索引的出现其实就是为了提升数据查询的效率,就像书的目录一样。一本 500 页的书,如果你想快速找到其中的某一个知识点,在不借助目录的情况下,那我估计你可得找一会儿。同样,对于数据库的表而言&am…

sqlite插入时间字段_sqlite 获取最后插入id

(点击上方公众号,可快速关注)SQLite数据库中的表均有一个特殊的rowid字段,它是一个不重复的64位有符号整数,默认起始值为1。rowid别名为oid或_rowid_,但在创建表的SQL声明语句中只能使用rowid作为关键字。如果在创建表的时候设置了…

Dubbo与SpringCloud的架构与区别

Dubbo与SpringCloud的架构与区别 Dubbo架构图 SpringCloud 架构图 总结 框架DubboSpringCloud服务注册中心ZookeeperSpring Cloud Netfix Eureka(nacos)服务调用方式RPCREST API服务监控Dubbo-monitorSpring Boot Admin熔断器不完善Spring Cloud Netflix Hystrix服务网关无Sp…

matlab求微分数值,用MATLAB语言求微积分方程的数值解.(xd^2y)/dx^2-5dy/dx+y=0y(0)=0y'(0)=0...

function dymyfun03(x,y)dyzeros(3,1) %初始化变量dydy(1)y(2); %dy(1)表示y的一阶导数,其等于y的第二列值dy(2)5/x*y(3)-y(1); %dy(2)表示y的二阶导数%ex0808 用ode23 ode45 ode113解多阶微分方程clear,clc[x23,y23]ode23(myfun03,[1,10],[1 10 30]);[x45,y45]ode45(myfun03,[…

springboot 接口404_资深架构带你学习Springboot集成普罗米修斯

这篇文章主要介绍了springboot集成普罗米修斯(Prometheus)的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧!Prometheus 是一套开源的系统监控报警框…

http常见的状态码,400,401,403状态码分别代表什么?

2XX 成功 200 OK,表示从客户端发来的请求在服务器端被正确处理 204 No content,表示请求成功,但响应报文不含实体的主体部分 206 Partial Content,进行范围请求 3XX 重定向 301 moved permanently,永久性重定…

mysql left 数学原理,MySQL全面瓦解21(番外):一次深夜优化亿级数据分页的奇妙经历...

背景1月22号晚上10点半,下班后愉快的坐在在回家的地铁上,内心想着周末的生活怎么安排。sql忽然电话响了起来,一看是咱们的一个开发同窗,顿时紧张了起来,本周的版本已经发布过了,这时候打电话通常来讲是线上…

java8中的map与flatmap区别

map:只能返回一个值 flatmap:返回多个值 new ArrayList().stream().map(x -> x);//返回一个 new ArrayList().stream().flatMap(x -> Arrays.asList(x.split(" ")).stream());//返回一个流,也就是多个值 看API声明可以发现,flatmap接受的参数是流…

shell 文件路径有空格_Python学习第57课-shell入门之基本简单命令(一)

【每天几分钟,从零入门python编程的世界!】我们现在学习shell操作,对于shell的命令,我们就把它看做新的语言,shell语言,它是不同于其他编程语言的。就像我们学习一门编程语言,都是从打出“hell …

比较Spring AOP和AspectJ

1. 介绍 当前有多个可用的AOP库,这些库必须能够回答许多问题: 它与我现有的或新的应用程序兼容吗?在哪里可以实施AOP?它与我的应用程序集成的速度有多快?性能开销是多少? 在本文中,我们将着眼…

hough变换直线检测_python+opencv实现霍夫变换检测直线

作者:Ruff_XY功能:创建一个滑动条来控制检测直线的长度阈值,即大于该阈值的检测出来,小于该阈值的忽略 注意:这里用的函数是HoughLinesP而不是HoughLines,因为HoughLinesP直接给出了直线的断点,…

php文件防删改,PHP实现增删改查以及防SQL注入

最近项目调研时,需要在集成板子上做个配置的网页,板子上装的是linux系统,配置信息在一个SQLite数据库中,经过讨论大家决定用PHP做这个网页。由于项目组没一个会PHP的,所以安排我调研下写个Demo,经过几天的研…