web表单设计代码,前端表单设计

一、背景

前端开发中涉及表单的页面非常多,看似功能简单,开发快速,实则占去了很大一部分时间。当某个表单包含元素过多时还会导致html代码过多,vue文件过大。从而不容易查找、修改和维护。为了提高开发效率及降低维护成本,下面介绍表单配置化组件的封装原理与封装方法。

二、技术方案

 

 

如上图所示,封装表单配置化组件的关键点有三个一是如何解决表单元素排布的行列问题,二是表单数据的绑定问题,三是表单元素的参数配置校验等问题。下面分别介绍这三个问题的解决方法。

•配置化表单组件的入参及说明

参数 说明 类型 可选值 默认值
labelWidth 表单元素label所占宽度 String —— 150px
columnList 表单元素所组成的配置,是一个数组 Array —— []
formData 表单元素值的集合 Object —— {}
columnSpan 表单排布分栏 Number —— 24
size 表单元素尺寸 String medium / small / mini medium

•计算配置化表单的行数,本表单通过基础的24分栏计算表单最终的行数和列数,通过下面方法最终得到一个关于行列的二维数组

newColumnList() {

  const newColumnList= []

  const row = Math.floor(24 / this.columnSpan)

  let newColumnItem = []

  for(let i=0; i< this.columnList.length; i++) {

    newColumnItem.push(this.columnList[i])

    if(newColumnItem.length === row || i === this.columnList.length-1) {

      newColumnList.push(newColumnItem)

      newColumnItem = []

    }

  }

  return newColumnList

}

•通过上面得到的二维数组进行循环渲染,首先循环渲染行,其次循环渲染列。本方案采用element中的表单,当然也可以用其他组件库或者原生表单进行渲染,其原理通用。最终将会根据参数column.type决定加载哪一个具体的表单元素。

<el-form ref="form" :model="formData" :label-width="labelWidth" :size="size">

    <el-row :gutter="20" v-for="(element,index) in newColumnList" :key="index+'formRow'">

      <template v-for="(item, index) in element" >

        <column

          :key="index + 'formView'"

          :columnSpan="columnSpan"

          :column="item"

          :formData="formData"

        />

      </template>

    </el-row>

</el-form>

•column组件最终根据type加载具体的表单元素。下面展示column组件的入参及其说明,通过component加载不同的表单元素

参数 说明 类型 可选值 默认值
column 表单元素的具体配置 Object —— {}
formData 表单元素值的集合 Object —— {}
columnSpan 表单排布分栏 Number —— 24
<el-col :span="columnSpan">

     <component

      :is="column.type + 'View'"

      :column="column"

      :formData="formData"

      v-model="formData[column.name]"

      :columnSpan="columnSpan"/>

 </el-col>



•这里主要以select表单元素为例进行说明,表单元素的双向绑定、校验以及值更新等问题

参数 说明 类型 可选值 默认值
column 表单元素的具体配置 Object —— {}
value 表单元素值 Number/String/Array —— ——

•column参数

参数 说明 类型 可选值 默认值
placeholder 空值说明 String —— ——
required 是否必填 Boolean —— ——
rules 校验规则 Array —— ——
title 表单元素label String —— ——
name 表单元素值名称 String —— ——
multiple 是否多选 Boolean —— ——
filterable 是否过滤 Boolean —— ——
disabled 是否禁用 Boolean —— ——
dictionary 下拉选项枚举 Array —— ——
changeFunction 值改变时的回调函数 Function —— ——
<el-form-item :label="column.title + ':'" :prop="column.name" :rules="rules">

    <el-select

      v-model="val"

      clearable

      :multiple="column.multiple"

      :filterable="column.filterable"

      :placeholder="'请选择' + column.title"

      :disabled="column.disabled"

      style="width: 100%"

      @change="onChange"

      @clear="onClear">

      <el-option v-for="item in column.dictionary" :key="item.code" :label="item.name" :value="item.code">

      </el-option>

    </el-select>

</el-form-item>



rules:  [

    {

      required: this.column.required,

      message: this.column.placeholder placeholder ? this.column.placeholder : `请输入${this.column.title}`,

      trigger: 'change'

    },

    ...this.column.rules

 ]
onChange(){

  this.$emit('input',this.val)

  if(this.column && this.column.changeFunction){

    this.column.changeFunction(this.val)

  }

},

onClear(){

  this.onChange()

}

三、项目实践

•配置化表单为bs-form,在页面中引入bs-form表单组件

<bs-form ref="formDemo"

     :columnList="columnList"

     :formData="formData"

     :columnSpan="columnSpan"

     labelWidth="120px">

</bs-form>

<el-row style="text-align: center;">

  <el-button type="primary"

             @click="onSave">保存</el-button>

  <el-button @click="onCancel">取消</el-button>

</el-row>



•formData参数

formData: {

    name: '',

    yearIncome: '', // 业务类型

    goodsCategoryId: '', // 托寄物品类id

    projectManagerErp: '', // 项目经理erp

    projectName: '', // 项目名称

    projectStage: '', // 项目阶段编码

    projectStandardName: '', // 标准名称

    projectYear: 2023, // 年份

    startRegionId: '', // 始发区域id

    startBattleId: '', // 始发战区id

    address: [], // 省市

    category: null, //图文类型

    range: [] //发布范围

 }



•分栏参数

columnSpan: 6

•表单配置参数

columnList(){

  const self = this

  return [

    {

      type: 'text',

      name: 'name',

      title: '项目名称',

      required: true,

      maxlength: 20,

      showwordlimit: true,

      placeholder: '请输入'

    },

    {

      name: 'category',

      type: 'radio',

      dictionary: [

        {

          code: 1,

          name: '类型一'

        },

        {

          code: 2,

          name: '类型二'

        }

      ],

      title: '图文类型',

      required: true

    },

    {

      name: 'range',

      type: 'checkbox',

      title: '发布范围',

      dictionary: [

        {

          code: 1,

          name: '范围一'

        },

        {

          code: 2,

          name: '范围二'

        }

      ],

      required: true

    },

    {

      type: 'text',  // 字段类型文本框

      name: 'yearIncome',  //与后台对接字段

      title: '年均收入',  // 前端展示字段

      required: true, // 必填项设置

      maxlength: 50,  // 字符串长度限制

      showwordlimit: true, // 是否显示字符串长度

      placeholder: '请输入', // 占位文本提示

      rules: [

        { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }

      ],

    },

    {

      type: 'select',

      name: 'goodsCategoryId',

      title: '托寄物品类',

      required: true,

      filterable: true,

      placeholder: '请选择',

      dictionary: [{

        name: '苹果',

        code: '1'

      },{

        name: '手机',

        code: '2'

      },{

        name: '测试',

        code: '3'

      },{

        name: '樱桃',

        code: '7'

      },{

        name: '荸荠',

        code: '9'

      }]

    },

    {

      type: 'select',

      name: 'startRegionId',

      title: '区域',

      required: true,

      placeholder: '请选择',

      dictionary: [{

        name: '销售-华北区域',

        code: '1'

      },{

        name: '销售-华东区域',

        code: '2'

      },{

        name: '销售-华南区域',

        code: '3'

      },{

        name: '销售-西南区域',

        code: '4'

      },{

        name: '销售-华中区域',

        code: '5'

      },{

        name: '销售-东北区域',

        code: '6'

      }],

      // 点击下来触发切换联动的事件,为一个函数

      changeFunction: function (val) {

      }

    }, {

      type: 'select',

      name: 'startBattleId',

      title: '战区',

      required: true,

      placeholder: '请选择',

      dictionary: this.battleByRegionList

    }, {

      type: 'select',

      name: 'projectStage',

      title: '项目阶段',

      required: true,

      placeholder: '请选择',

      dictionary: [{

        name: '项目发起阶段',

        code: '10'

      },{

        name: '项目调研阶段',

        code: '20'

      },{

        name: '可行性分析阶段',

        code: '30'

      },{

        name: '立项阶段',

        code: '40'

      }]

    }, {

      type: 'text',

      name: 'projectStandardName',

      title: '标准名称',

      required: true,

      placeholder: '请输入',

      append: '.com',  // 文本框后置内容

    }, {

      type: 'text',

      name: 'projectManagerErp',

      title: '项目经理',

      required: true,

      placeholder: '请输入'

    },{

      type: 'cascader',  // 字段类型下拉框

      name: 'address',   //与后台对接字段

      title: '省市区',  // 前端展示字段

      required: true, // 必填项设置

      placeholder:'请选择',  // 占位文本提示

      dictionary: [{

        value: 'shanxi',

        label: '陕西省',

        children: [{

          value: 'xian',

          label: '西安市',

          children: [{

            value: 'yanta',

            label: '雁塔区'

          }, {

            value: 'beilin',

            label: '碑林区'

          }, {

            value: 'xincheng',

            label: '新城区'

          }, {

            value: 'weiyang',

            label: '未央区'

          }]

        }]

      }],

      // 点击下来触发切换联动的事件,为一个函数

      changeFunction: function(){}

    },{

      type: 'static',

      name: 'projectYear',

      title: '年份'

    }

  ]

}

•表单保存

// 保存

async onSave() {

  const valid = await this.$refs.formDemo.onValidate()

  if(valid) {

    this.$message.success('校验通过')

  }else {

    this.$message.error('校验失败')

  }

}

四、成果展示

本站部分内容由互联网用户自发贡献,该文观点仅代表作者本人,本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如发现本站有涉嫌抄袭侵权/违法违规等内容,请联系我们举报!一经查实,本站将立刻删除。

(0)

相关推荐

  • 网易邮箱助手,网易个人邮箱密码忘记了怎么办啊

    方法一:通过安全手机验证更改邮箱密码,登录(https://reg.163.com/naq/findPassword?mreg=1#/verifyAccount),根据页面提示操作修改密码(如下图所示); 选择验证方式,进行验证即可(如下图所示); 方法二:如您目前忘记邮箱密码且绑定安全手机无法验证/未绑定安全手机,请您按照以下步骤提交帐号修复,修复成功后可…

    2023-07-09
  • 金点子小生意(金点子生意杂志上的小点子)

    创业和打工哪个好?答案是没有绝对的,因人而异,如果你喜欢挑战,那么你可以选择创业,这里就有几个农村创业的点子,投入本钱不大,但都能赚上好多万,看了后你会如何选? 1、烧羊技师经济人 烤全羊一直都是各地受欢迎的美食,但是烤全羊得师傅流动性都比较大,烤全羊的工作具有灵活性,一个烤全羊得师傅可以接应很多商家的活,比如今天在张家烤,明天可以到李家烤,只要有活做,他们…

    投稿 2021-12-27
  • 速汇宝第三方支付(汇通支付平台)

    移动支付网消息:5月17日,花旗银行(中国)发布《关于花旗银行全球速汇通服务变更的通知》。通知显示,自2022年6月17日起,其用户将无法通过花旗全球速汇通服务向**花旗银行账户进行转账或接受来自**花旗银行账户的汇款。自2022年6月26日起,花旗银行中国将全面停止提供全球速汇通服务,同时用户的收款人名单中全球速汇通收款人信息将被自动移除。 届时,用户可以…

    2023-01-31
  • 非洲最大的岛屿(非洲最大的岛屿位于非洲的哪里)

    地球表面大约有21%的面积被陆地覆盖,总面积大约为1.49亿平方千米,当然地球表面的陆地并不是完整的一块,而是分割成许多部分分布在地球表面。从半球来看,北半球的陆地面积大于南半球,东半球的陆地面积大于西半球。根据陆地面积的大小我们分为“大陆”和“岛屿”两类,地球上的大陆总共有六个大陆,分别是亚欧大陆、非洲大陆、北美大陆、南美大陆、南极大陆和澳大利亚大陆,其中…

    2022-05-10 投稿
  • 激素过敏,网购护肤品过敏怎么办

    楚天都市报8月4日讯(记者刘毅)因为脸部皮肤对化妆品过敏,家住洪山的伊女士本想网购一款护肤品保养一下皮肤,可4日她发现卖家宣称能解决他皮肤问题的护肤品又让她出现过敏症状了。 伊女士说,半年来自己脸部皮肤经常过敏,一晒太阳或者用一些化妆品脸就出现泛红等过敏症状,为此她还到医院治疗过。上月,她在网上发现一款名为“9LAB”的护肤品,该产品广告称对皮肤过敏有作用,…

    投稿 2023-07-12
  • 历史上真有东北张家吗(东北张家都有谁)

    对于《盗墓笔记》中的东北张家,可能很多人会印象深刻,尤其是闷油瓶小哥那只不同寻常的右手,更是令很多人充满好奇。当然,大家都知道东北张家是一个神秘家族,通过盗墓活动,聚集着大量财富,内部控制着中国几千年的王朝更迭秘密。那么故事里面的东北张家,究竟有多厉害呢?可能大家都还不知道,几乎可以说中国历史上的很多王朝都是毁在张家人手里。具体情况,且看书法家破石细细道来。…

    投稿 2023-04-10
  • 福缘论坛官网金业靠谱吗(网站结合互联网)

    QY:狼哥,我想搜索一些百度云盘的资源,到哪里去搜索? 这三四年一般来讲,我都是用盘多多这一个网站去搜索。类似的猎手导航,虫部落,搜盘盘,西林街,盘多多这个软件比较好用,它可以根据时间文件大小进行分类。 QY:狼哥,想制作我的喜马拉雅封面效果图用什么软件? 如果你会用ps的话,最好就用这个。这个也可以套模板,非常简单,你也可以用创客贴这个网站,非常的齐全,做…

    投稿 2022-01-07
  • 赚呗真的能赚钱吗(赚呗是正规的平台吗)

    茂名晚报讯记者林夏通讯员于兵万一团伙注册电子商务科技公司,购买多个虚假投资软件,招募员工进行话术培训,按照话术引诱他人在虚假投资平台投资,通过后台操控涨跌,致使投资者在不知不觉中遭受损失。 近日,经广东省茂名市电白区检察院依法提起公诉,该“微投资”诈骗团伙16名团伙成员被法院依法判处有期徒刑6年6个月至1年1个月不等刑期,并处罚金。 2.3万元的投资平台与国…

    投稿 2022-01-09
  • 阿里旺旺上不去怎么回事(阿里旺旺登陆不上怎么办)

    对于阿里旺旺APP,的确都没有听说过,竟然还出APP了,之前在电脑上,有时候用淘宝或者天猫购物的时候,有时候需要沟通很久,网页端会提醒下载阿里旺旺软件,还下载用过,特别是给我们企业负责采购的事情,要一次性问很多商品,而且购买上千份所以必须要对比,自然聊天用的多,就下载了!   到后面使用手机购物成为常态的时候,还真没有听说过这个APP,因为一般基于…

    2021-12-06 投稿
  • 相爱十年插曲,《相爱十年:永恒的爱情宣言》

    新华社北京10月18日电 题:为如期实现建军一百年奋斗目标砥砺奋进——全军官兵认真收听收看党的二十大开幕会并展开学习讨论 新华社记者 同心向党庆盛会,凝心聚力向复兴。 16日上午,党的二十大在京隆重开幕,**总书记代表第十九届中央委员会向大会作报告。 从军委机关到任务部队,从边防海岛到异国他乡,从荒漠戈壁到深山密林……全军官兵通过广播、电视、网络等认真收听收…

    投稿 2023-05-11
  • OPENWHO官方入口,openwhu

    在当今数字化的时代,人们对于各种官方入口的需求日益增长。 它究竟是什么?在哪里可以找到它?它又有着怎样的作用和意义呢?接下来,让我们一起深入探讨这个话题。 也许它是WorldHealthOrganization(世界卫生组织)的一个分支或特定计划,旨在通过开放的数据和信息共享,推动全球健康事业的发展。 我觉得它可能类似于一个平台,汇聚了世界各地的健康数据、研…

    投稿 2025-04-13
  • 26字母键盘指法训练(26字母键盘指法训练软件)

    在零基础的情况下,迅速通过自学键盘打字还需要下一定的功夫,首先,可以肯定的是,有许多按钮在键盘上,键盘有很多功能,划分为不同的区域,最常见的使用是主要的键盘区域,和打字在电脑上使用最是主键盘区26个英语字母是关键。因此,让我们从26种使用字母键进行输入的方法开始   首先,掌握从A到Z的26个英文字母,这是最基本的,最基本的知识,我相信很多人从小就…

    2021-12-17 投稿