ng官方有一套十分强大的表单校验工具,就是FormController
简单来说这东西的作用,就是把校验逻辑和双向绑定modelValue给抽象到同一个强大的对象上,结果就是,在vue和react中能看见的FormItem这种标签或者react的高阶组件,在ng中是不需要的**(这最本质的原因就是,angular通过directive指令机制能方便得改造组件,不需要像vue/react那样包裹一层组件就能实现改造,并且formController直接代替modelValue的职责承载双向绑定的能力,丝滑接入)**
也就说,每一个formController都存储了这个表单域的值和校验信息,而且校验状态还分地很细致,根据这个表单是否被foucus和校验失败等,有初始状态,touched状态,dirty状态等,具体怎么对应的还要重新查证
因为我最开始是使用ng开发的,看惯了formCtrl后,发现vue和react还需要大量的嵌套标签,其实就有点嫌弃。当然,我是挑ng好的说。所以ng的表单管理真的很好,还不止上面说的,还有group的概念,可想而知,就是如果按组分类之后,你将能十分轻松地获得一组组的表单的整体校验是否通过。
除此之外,formController还有array的概念,很多时候,我们可能会以一行特定的字段为一个单位集合,在表格中for循环,每一行都应该可以动态增删,而这样的表单模型,很显然是array结构的。很显然,在这样的模型下,你无需关心每个字段的值的管理,因为每个formCtrl即存储校验状态也存储值。
之前开发的时候,有一点十分不解,formCtrl的api中竟然没有为一个字段提供动态移除单个校验函数的api,而只能一次性移除所有校验和一次性添加多个校验。当时正好项目里的formCtrl还套了一层公司封装的壳,正好每个字段还多冗余存储了一份校验规则数组,于是我就根据这个数组,来添加了可以动态删除指定的单个或多个校验的方法。真的好用。特别时跨field的联动校验,真的很需要动态添加删除校验的api。比如某个下拉中选中某几项时,就能移除另一组字段的必填校验。
后来我把这个功能移到ant-design-vue上,提了个pr,作者给我说下个版本就上这个功能,结果后来没管我的pr,被自动关闭了。我想原因应该是,我实现方式是深度watch了那个返回rules对象的计算属性,不太安全,即便我已经给rules前后进行了深拷贝对比,理论上这种小对象也不会有什么太大的开销,应该是能接受的,但也许还是觉得不安全的,最终还是没看到上线。
现在在学习react的过程中,我希望我能回忆一下angular的好
对了,至于react,我感觉好像是为了保持react整体的纯洁和纯粹性,竟然react都没有双向绑定的组件指令的,乖乖写props和onChange来做值的传递和更新。当然,我相信一定更好的实践写法
===========update
react/vue的表单检验,实属拉跨
- 当然这是ui库的锅,但官方肯定也不会做这个,那到底是谁的锅?
- ant-design中Form.List的api十分简单,主要依靠children属性,作为渲染函数,但各个传入参数文档确没有说明,令人十分费解
- vue的ant-design中FormItem的rule对象变化,不能触发表单实时更新校验
- react的ant-design中FormItem的rule 对象变化可以实时更新form校验,但react 受控组件比较麻烦。虽然有建议用useReducer + 大对象来管理表单数据,但是,这不就高耦合了,理想情况下不同field之间应当互不影响,代码逻辑分离解耦
- 有什么好办法?不知道
- react适合做ui,但真的表单管理比ng差很多
- vue带oop思想,有双向绑定在表单管理上比react好点