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('校验失败')

  }

}

四、成果展示

本文来自投稿,不代表展天博客立场,如若转载,请注明出处:https://www.me900.com/325503.html

(0)

相关推荐

  • 视频照片合成软件有哪些?视频照片合成软件哪个好

    视频合并软件有哪些?拍摄视频是我们日常生活中常见的一种记录方式,如果视频片段太长怎么办?如果视频片段太碎怎么办?不要慌,只需要将将视频进行合并再发布就可以了,不过合并视频仅仅是要将多个不相干的视频片段合并为一个导出,还要保证视频画质不会造成任何损坏,那么,小编推荐的这两款视频无损合并神器别错过! 软件一:彩虹办公软件 彩虹办公软件是一款独特丰富的智能模式操作…

    2023-01-28 投稿
  • 巴拉达尔 阿富汗总统,布托啡诺

    1976年5月27日,毛主席强撑病体完成了他生前最后一次外宾接待工作,这也是他最后接见的一位外国领导人。 他就是巴基斯坦时任总统,佐勒菲卡尔阿里·布托。 阿里布托在担任巴基斯坦总统期间,与各国保持着友好的外交关系,国际上享有声誉,国内也深受民众爱戴,他雄心十足,曾想要打造一个和谐的民主社会,却因走错了一步棋,最终殒命于绞刑架,使人叹息。、 深得民心:从律师到…

    2023-07-10
  • 大连最新一例疫情是在哪住的(大连最新疫情在哪个区)

    11月19日大连市新冠肺炎疫情防控总指挥部发布,11月18日0时至24时,大连市新增7例本土新冠肺炎确诊病例,均在密切接触者和重点人群主动排查中发现。 现将确诊病例主要活动轨迹公布如下: 确诊病例281:甘井子区某公司员工,居住地为金普新区先进街道响泉社区万科城小区。11月7日—15日,先后4次核酸检测阴性;11月18日在重点人群主动排查中核酸检测阳性,随即…

    2021-12-28
  • 王国战役,理清英国2000年历史的故事

    英国曾经是世界上最强大的国家,它开创了一个崭新的文明。虽然如今的英国已经不复当年,但是由它所开创的新文明却延续至今,并且遍及全球。一个国家崛起与衰落的过程与原因,都可以从历史中找到答案。这次就让我用一篇文章,简单梳理一下英国数千年的历史,为你理清其基本脉络。 英国全称是大不列颠及北爱尔兰联合王国,由英格兰、威尔士、苏格兰、北爱尔兰四部分组成,英国历史一共可以…

    2023-07-09 投稿
  • 淘宝全球购是正品吗,淘宝全球购是正品吗 知乎

    《淘宝全球购是正品吗?》 在当今的电商时代,淘宝全球购作为一个备受关注的购物平台,其商品的真伪问题一直是消费者心中的疑虑。 许多人在考虑在淘宝全球购上购买商品时,都会纠结于“淘宝全球购是正品吗?”这个问题。 那么,淘宝全球购到底是不是正品呢?让我们一起来探讨一下。 一、淘宝全球购的背景与特点 淘宝全球购是淘宝旗下的一个跨境电商平台,旨在为消费者提供全球范围内…

    2025-03-28
  • 传奇英雄故事,抗日英雄海娃的故事

    为加强小朋友们对党史、国情知识的深入了解,引导大家能够在少先队组织里立志向、修品行、练本领,传承红色基因,争做时代新人。日前,“小舞台 大梦想”丽江市青少年职业体验实践系列活动走进丽江市广播电视台,参加活动的13位小朋友们,走上主播台,当了一回小小播音员。 丽江新闻综合广播FM106.2《纳西瑞瑞》栏目,通过少儿讲党史故事的方式,了解中国共产党一路走来的艰辛…

    2023-07-04 投稿
  • 销售如何推广自己的产品(地产渠道12种拓客方式)

    企业获客方式哪种靠谱?中小型企业推广有什么难题? 网络技术的发展对中小民营企业来说既是机遇也是挑战。如何利用网络优势开展网络营销、制定营销策略、提升竞争优势成为中小民营企业主共同关注的问题。本文在深入分析网络环境下中小民营企业营销现状的基础上,提出了一些营销策略。 中小型企业推广老旧的推广方式: 广告费用投入高:比如做线下推广,需要投入大量的推广经费去做广告…

    2022-01-03
  • 网拍能赚多少钱一天(网上拍视频能赚多少钱)

    一个视频能不能给你赚2000元 你做不做得到,如果做不到,你看着羡慕吗。 如果你也想在头条甚至视频上分一杯羹,那你一定要看完这篇文章。 在今天之前我也许不会去想的这么远和不切实际,但今天惊到我了。 原因就是我的做鸡翅视频,昨天的收益今天出了。 千次播放单价20,可播放量上不去   自从加入中视频开始我就比较注意视频的收益,毕竟我一开始做这个的初衷也…

    2021-11-09
  • 金星的军衔有多高(金星政治身份)

    在娱乐圈中,不乏有来自各大名校的优秀演员,还有怀揣着明星梦的少男少女们,更有响应国家号召入伍的文艺兵。当然巾帼不让须眉,自然这其中也有不少的女明星也是出身于军人中,下面就让我们来盘点6位带有军衔的女明星吧!   第六位:陈红 说到这个名字,大家首先想到的应该是演员陈红,但此“陈红”非彼“陈红”,这一位呢!则是凭借歌曲《常回家看看》红遍大江南北的歌手…

    2022-01-05 投稿
  • 小ck有几种标志(小ck标志正品字母)

    “包包全部5折,但不知道是不是正品!”来自重庆巴南区的胡女士在社交论坛上传了一张自己在观音桥步行街中央看到的“小CK”展台位及包袋照片。不少网友在评论区回复她,“明显是假的”,“字母都拼错了”。 “款式几乎全部跟‘小CK’的一样,不仔细看还真没发现。”和胡女士有相似经历的消费者不在少数。近日,界面重庆走访发现,被消费者称作“小CK”的新加坡快时尚品牌CHAR…

    2021-12-26
  • 销售新人三个月不开单正常吗(不适合做销售)

    你是不是想壮大你的销售团队呢? 你是不是想招几个新人来接替那些即将离职的销售人员? 你是不是希望这些新招的销售人员可以快速上手,尽早开单呢? 如果你有这些期望的话,你需要先采用CRM系统。 CRM系统的很多功能可以帮助企业让新招的销售人员入职过程更加平稳高效,减少工作交接时的麻烦,同时帮助销售新人更快地了解公司的销售流程和销售方法,从而更快地产出业绩。 &n…

    2021-12-18 投稿
  • 1974年属虎一生婚姻如何(74年属虎为何婚姻不顺)

    经历了世间的至苦,方能看破凡尘。以一颗淡然的心,去理解过往的悲喜。虽青涩,但也是一道美丽的风景。感谢走进你生命中的那些人,因为她们让你成长,让你理解自己的缺点与不足。以一颗豁达的心,去面对未来的人生。不再执着于某些人,某些事。   生肖虎的朋友们做事成熟稳重,他们容易给人踏实感,所以他们无论做什么都会很出众。一月,他们命中将有横财降临,一路大发。不…

    2022-03-19 投稿