Vue3组件(九)封装一个长大的表单(上)

一个神奇的表单

表单表单,你已经长大了,你要学会自己:

  • 排成一列
  • 排成一行
  • 验证表单数据
  • 排成方队
  • 合并调整
  • 动态渲染
  • 支持 item 扩展组件
  • 可以自动创建 model

实现多行多列的表单

首先感谢 el-form,真的很强大,不仅好看,还提供了验证功能,还有很多其他的功能。
只是好像只能横着排,或者竖着排。那么能不能多行多列呢?似乎没有直接提供。

我们知道 el-row、el-col 可以实现多行多列的功能,那么能不能结合一下呢?官网也不直说,害的我各种找,还好找到了。(好吧,其实折腾了一阵着的table)

二者结合一下就可以了,这里有个小技巧,el-row只需要一个就可以,el-col可以有多个,这样一行排满后,会自动排到下一行。

  <el-form ref="form" :model="formModule" label-width="130px">
      <el-row>
        <!--不循环row,直接循环col,放不下会自动往下串行。-->
        <el-col :span="8">
           <!--假装有好多好多的el-col-->
           <el-form-item :label="姓名:">
              <!--这里可以放组件-->
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

这样有什么好处呢?当然是便于我们做v-for呀,给 el-col 加上 v-for 就好。

实现动态渲染功能

表单嘛,那么多字段一个一个做多麻烦,v-for 一下不香吗?
前面封装了那么多的组件,就是为了可以 v-for。

首先准备一个json文件,里面放置需要的组件的属性。


003表单的json.png

json比较长,我们还是看截图吧,直观一些。

然后用 require 读取进来,当然也可以用 axios 来读取。

然后表单控件就可以用这些属性做循环了。

另外还有几个附带功能:

  • 支持单行下的合并。
    在单行的情况下,一些短的控件会比较占空间,我们可以把多个小的合并到一行。

  • 支持多行下的扩展。
    多行的情况下,一些长的控件需要占更多的空间,我们可以设置它多占几个格子。

  • 自动创建表单需要的 model。
    不需要手动写 model了。

自动创建 model

我比较懒,手撸 model 是不是有点麻烦?如果能够自动获得该多好,于是我写了这个函数。

  // 创建 v-model
  const createModel = () => {
    // 依据meta,创建module
    for (const key in formItemMeta) {
      const m = formItemMeta[key]
      // 根据控件类型设置属性值
      switch (m.controlType) {
        case 100: // 文本类
        case 101:
        case 102:
        case 103:
        case 104:
        case 105:
        case 106:
        case 107:
        case 130:
        case 131:
          formModel[m.colName] = ''
          break
        case 110: // 日期
        case 111: // 日期时间
        case 112: // 年月
        case 114: // 年
        case 113: // 年周
          formModel[m.colName] = null
          break
        case 115: // 任意时间
          formModel[m.colName] = '00:00:00'
          break
        case 116: // 选择时间
          formModel[m.colName] = '00:00'
          break
        case 120: // 数字
        case 121:
          formModel[m.colName] = 0
          break
        case 150: // 勾选
        case 151: // 开关
          formModel[m.colName] = false
          break
        case 153: // 单选组
        case 160: // 下拉单选
        case 162: // 下拉联动
          formModel[m.colName] = null
          break
        case 152: // 多选组
        case 161: // 下拉多选
          formModel[m.colName] = []
          break
      }
      // 看看有没有设置默认值
      if (typeof m.defaultValue !== 'undefined') {
        switch (m.defaultValue) {
          case '':
            break
          case '{}':
            formModel[m.colName] = {}
            break
          case '[]':
            formModel[m.colName] = []
            break
          case 'date':
            formModel[m.colName] = new Date()
            break
          default:
            formModel[m.colName] = m.defaultValue
            break
        }
      }
    }
    // 同步父组件的v-model
    context.emit('update:modelValue', formModel)
  }

可以根据类型和默认值,设置model的属性,这样就方便多了。

多列的表单

这个是最复杂的,分为两种情况:单列的挤一挤、多列的抢位置。

单列

单列的表单有一个特点,一行比较宽松,那么有时候就需要两个组件在一行里显示,其他的还是一行一个组件,那么要如何调整呢?

这里做一个设定:

  • 一个组件一行的,记做1
  • 两个组件挤一行的,记做-2
  • 三个组件挤一行的,记做-3
    以此类推,理论上最多支持-24,当然实际上似乎没有这么宽的显示器。

这样记录之后,我们就可以判断,≥1的记做span=24,负数的,用24去除,得到的就是span的数字。当然记得取整数。

为啥用负数做标记呢?就是为了区分开多列的调整。

多列

多列的表单有一个特点,一个格子比较小,有些组件太长放不下,这个时候这个组件就要抢后面的格子来用。

那么我们还是做一个设定:

  • 一个组件占一格的,还是记做1
  • 一个组件占两格的,记做2
  • 一个组件占三格的,记做3
    以此类推。

这样记录之后,我们可以判断,≤1的,记做 24 / 列数,大于1的记做 24/ 列数 * n。
这样就可以了,可以兼容单列的设置,不用因为单列变多列而调整设置。
只是有个小麻烦,占得格子太多的话,就会提取挤到下一行,而本行会出现“空缺”。
这个暂时靠人工调整吧。
毕竟哪个字段在前面,还是需要人工设置的。

一顿分析猛如虎,一看代码没几行。

  // 调整行列
  const span = reactive({})
  // 根据配置里面的colCount,设置span
  const getSpan = () => {
    const formColCount = formMeta.formColCount // 列数
    const moreColSpan = 24 / formColCount // 一个格子占多少份

    if (formColCount === 1) {
    // 一列的情况
      for (const key in formItemMeta) {
        const m = formItemMeta[key]
        if (typeof m.colCount === 'undefined') {
          span[m.controlId] = moreColSpan
        } else {
          if (m.colCount >= 1) {
            // 单列,多占的也只有24格
            span[m.controlId] = moreColSpan
          } else if (m.colCount < 0) {
            // 挤一挤的情况, 24 除以 占的份数
            span[m.controlId] = moreColSpan / (0 - m.colCount)
          }
        }
      }
    } else {
      // 多列的情况
      for (const key in formItemMeta) {
        const m = formItemMeta[key]
        if (typeof m.colCount === 'undefined') {
          span[m.controlId] = moreColSpan
        } else {
          if (m.colCount < 0 || m.colCount === 1) {
            // 多列,挤一挤的占一份
            span[m.controlId] = moreColSpan
          } else if (m.colCount > 1) {
            // 多列,占的格子数 * 份数
            span[m.controlId] = moreColSpan * m.colCount
          }
        }
      }
    }
  }

最后看看效果,可以动态设置列数:

动态表单001.gif

如果空间够的话,最多可以是24列。应该是够用了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容