方便不想看完全篇文章的童鞋,简单总结一下,这是篇软广,主要是推广自己在业务中沉淀的一个开源组件 vue-dynamic-form-component 。基于 element-ui 实现的 vue组件,只需编写类似 async-validator 的规则,自动生成对应的表单,支持常见输入类型的同时,支持嵌套对象、hashmap、多维数组等复杂类型。有需要的童鞋欢迎使用和贡献代码,顺便给个star(我也不知道为什么字体自动加黑了,不关我事)
前言几个月前,我在github开源了一个前端解析手机应用安装包(IPA 或 APK 文件)信息的工具 app-info-parser ,算是第一次正儿八经的做开源这件事,之后就有了半夜三四点回复issue、修bug的体验,说实话,上完班还要处理issue是挺累的,但也是乐在其中。正所谓开源一时爽,一直开源一直爽。
对于程序员而言,最不喜欢的事情,除了和产品经理 吵架 (交流,是交流,不是吵架,要peace)外,估计就是一直做重复的事情了。在程序界,有相当一部分开源工具都是为了把人从重复的事情中解放出来,去做更有趣、更能体现个人价值的事情。比如 AI智能回复老婆消息 (请勿随意尝试,老婆没了我不负责)。
之前开源的工具 app-info-parser 是减少重复工作,提高生产效率,接下来的主角 vue-dynamic-form-component 也是如此。
先贴一个展示大概功能的 gif ,动图有点大,如果加载不出来的话可以到 组件首页 查看。
左边是你需要编写的主要代码,右边是对应生成的表单。
背景(Why)为什么要做这个组件?其实在前言中已经提到:因为不想一直做重复、没有技术含量的事情。
对于本篇文章而言,这件重复、没有技术含量的事情就是:简单的表单代码
我所在的小组主要负责公司的公共服务系统搭建及维护,随之而来的便是一套接一套的CURD系统,目前业界已经存在很多优秀的UI库,比如为 Vue 而生的 element-ui, iView,基于 react 的 ant-design 等,已经在很大程度上提高了PC管理系统的开发效率,减少了很多重复工作。
但是对于表单功能,UI库出于通用性的考虑,实际使用中,对于简单的数据对象,我们仍然需要编写大量的表单代码来实现,因为出现了很多优秀的动态表单组件,比如 vue-form-generator,vue-form-making
那么为什么我还要再造一个类似的轮子?这其实要结合组内的技术栈来说:
由于组内的人员配置问题:前端1人(没错,就是孤独的我)、后端8人+,在技术栈上,选用了后端同事相对容易上手的 Vue ,基于 element-ui 开发管理系统。而目前已有的动态表单组件存在以下不适用的问题:
vue-form-generator:设计思想很好,但是组件样式比较old school,同时对多级对象、多维数组等复杂数据支持不是很好,需要自己实现 field 组件,使用成本较高vue-form-making:也是基于element-ui, 样式统一,但是基于组件类型生成表单的方式不够灵活,只能利用已存在的输入组件,因此不支持多级对象等复杂类型其他的组件相对而言存在更多的问题,就不一一列举了。
以上就是为什么我会想要再造一个Vue的动态表单轮子,其实里面就已经包含了接下来我们要讲的: vue-dynamic-form-component 有什么作用?
功能(What)动态生成表单基于 async-validator 的规则来生成表单,只需要编写简单的声明配置,即可自动生成表单,只需要关注数据类型,无需关注数据类型对应何种输入组件
<template> <dynamic-form v-model="data" :descriptors="descriptors"> </dynamic-form></template>export default { data () { return { data: {}, descriptors: { date: { type: 'date', label: 'date \'s label', required: false }, number: { type: 'number', label: 'number \'s label', required: true, placeholder: 'please input the number' }, string: { type: 'string', label: 'string \'s label', required: true, pattern: /^test$/g }, url: { type: 'url', label: 'url \'s label', required: true, placeholder: 'please input the url' }, email: { type: 'email', label: 'email \'s label', required: false }, enum: { type: 'enum', label: 'enum\'s label', enum: ['value-1', 'value-2'] } } } }}
...