前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写前端就是写表单?

写前端就是写表单?

作者头像
前端小哥哥
发布2023-05-04 19:46:01
4120
发布2023-05-04 19:46:01
举报
文章被收录于专栏:前端小哥哥前端小哥哥

首先,大家思考一下表单是什么?前端又是什么?


表单是什么?

小弟不才,曾有幸参与某中台的表单引擎的开发工作,一般开发前我们都是先用领域设计模型分析一波,时间的关系,先上图

用现在流行的八卦文翻译一下就是要先找出业务的聚合根,再分析它的属性,然后再总结它的生命周期 最后我们得出的结论是: 写前端不等于写表单 本文终。

前端是什么?

那写前端到底是写什么? 本人才疏学浅 我认为人机需要交互的地方都属于前端 包括但不限于全息控制、人脑控制、声音控制、AR、VR 所以说要立志要做大前端的那位 你们以后的css样式可能还要加上声音/气味属性了

代码语言:javascript
复制
.flower:{
  color: yellow;
  sound: quiet;
  smell: sweet;
}

我设计的表单

但相信大家都同意的是,表单开发在日常的开发中,应该是最复杂,占用的时间应该是最多的 我先来随便说几点:

  • 动态表单生成
  • 多级联动
  • 动态校验
  • 定制业务组件
  • 嵌套子级表单
  • 数据反显
  • 编辑状态禁用
  • 等等

某知名博文《写前端就是写表单?》的博主曾经说过:“控制最小边界,组合,就是好架构” 所以我们先设计一个最小的表单

最小的表单

1.要有一个<form></form> 2.要有一个formData 3.要有一个控件配置表

配置表

建一个form-register.ts 的文件

ts, 是的我加了ts 就是将所有组件import进来 再export出去 规范点的话还能用require.context动态引入

代码语言:javascript
复制
import Text from './Text/index.vue'
//类型
export  formConfigs:formTypes= {
  text: Text
}

眼利的朋友应该发现有一个formTypes

代码语言:javascript
复制
//组件的class很强大,可以直接作为类型
export interface formTypes {
  Text?: Text
}

那还有一个最关键的别人调用的配置项是长怎样的呢,以下是我的参考,具体可以根据自己业务需要自行添加

代码语言:javascript
复制
export interface fieldType {
  fieldType: keyof formTypes
  key: string
  dict?: string
  type?: string
  name?: string
  label?: string
  placeholder?: string
  required?: boolean
  isShow?: Function //是否显示
  dateType?: 'date' | 'time' | 'year-month' | 'month-day' | 'datetime'
  readonly?: boolean
  rules?: rule[]
  isWrap?: boolean
  hiddenLabel? :boolean
  extraKey?: string | extraKeyType[]
  formDataFormatter?: Function //格式化函数
  formDataConvert?: Function // 转换成多个其他值
  propShowValue?:string //显示的字段
  handleChange?: Function
  [k: string]: any
}

大家发现会有一个[k: string]: any,需然牺牲了一些类型约束,但是换来的扩展自由也是很有价值的

组合

加入了一个动态组件渲染

代码语言:javascript
复制
<form>
  <template v-for="fieldItem in fieldList">
    <component
      :key="fieldItem.key"
      :is="formRegister[fieldItem.fieldType]"
      :fieldItem="fieldItem"
      v-bind="fieldItem"
      v-model="formData[fieldItem.key]"
    ></component>
  </template>
</form>

这里用到v-bind把所有属性props进去,react的话可以自己解构...props 到这里如无意外的话,你的表单组件应该渲染出来了 但有人可能就会问,也不是杠什么的,你的fieldList是怎样来的

函数生成器

当初设计的时候第一直觉,就是props一个fieldList的数组进来 但后来遇到一些问题

  • 组件之间联动
  • 数据值强绑定
  • 表单项动态生成
  • 校验规则条件动态变化
  • 等 可能都要监听formData值的变化,再改变fieldList的值

后来,某天发呆的时候,想到《上帝掷骰子吗》一书中,对多宇宙的一个解说是,每个世界线的变动都会再产生出一个新宇宙

好家伙,那我们为什么不能写一个多宇宙的表单组件呢?每次formData值的变动就再产生出一个新的fieldList fieldListMaker诞生 我马上改成如下:

代码语言:javascript
复制
get formDataString() {
  return JSON.stringify(this.formData)
}
@Watch('formDataString', { immediate: true, deep: false })
formDataChanged(val: any, oldVal: any) {
  if (val !== oldVal) {
    this.fieldList = this.fieldListMaker(val)
  }
}

formData转为string监听,为了避免一些深层次的属性变化监听不到 传入的时候fieldListMaker长这样

代码语言:javascript
复制
fieldListMaker(formData: any): Array<fieldType> {
  // 你在这里可以做你想做的各种东西😊
  return [
    {
      fieldType: 'text',
      key: 'abc',
      label: 'def'
    }
  ]
}

总结

实际使用就是

代码语言:javascript
复制
import FormList from '@/components/form/index.vue'
<FormList
  ref="formRef"
  :fieldListMaker="fieldListMaker"
  :showBtn="false"
  @change="handleFormChange"
/>

大家可以根据各自喜好,在里面添加一些方法,如:

  1. 校验方法
  2. 设置属性值方法
  3. 清空校验方法
  4. 强制更新list方法
  5. 等 各种业务表单组件也可以自己添加,只要约定好一些基本方法,里面@Model(‘change’)出来一个双向绑定就好了 真.完结,撒花

彩蛋

有兴趣的可以看源代码多宇宙表单

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 表单是什么?
  • 前端是什么?
  • 我设计的表单
    • 最小的表单
      • 配置表
        • 组合
          • 函数生成器
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档