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)

相关推荐

  • 宝路华手表世界排名(宝路华手表排名第几)

    2021年年底的时候,宝路华发布了MIL Ships腕表,提醒了世界不要忘记他们的制表实力。但在此之前,该品牌还发布了另一款军事主题的复刻作品:宝路华Hack腕表,但它却并未掀起什么大的波澜。该表款是为了纪念二战期间发给美军使用的宝路华手表而打造的,其表盘使用的是简约传统的黑白配色。之后品牌又推出了24小时红标的版本,而现在,宝路华在不牺牲灵感根源的基础上转…

    2023-02-10 投稿
  • 炼乳吃法大全(炼乳吃法大全不用烤箱)

    最近发现了一个吐司的神仙吃法,带着炼乳的香甜,一口就可以吃掉的西多士,赶紧做起来! By 丁当老娘 用料 吐司 10片鸡蛋 3个牛奶 150克炼乳 适量 做法步骤 1、吐司片切成小方块。 2、鸡蛋打入碗内。 3、加入牛奶。 4、搅散混合均匀备用。 5、抹上炼乳。 6、另取一块重叠。 7、放入奶蛋液里滚一圈。 8、放入空气炸锅中。 9、10分钟左右。 10、1…

    2022-05-10 投稿
  • 菜鸟是什么意思,菜鸟是什么意思网络流行语言

      在东西方文化中,“笨鸟”、“菜鸟”似乎都成了通用的贬义词,好像鸟类都是很愚蠢的动物一样,但事实上,这你可就错怪它们啦!最新的研究表明,鸟类远比人们想象得要聪明。 可能你会觉得,鸟有什么聪明的?不就是长了两个翅膀,能飞来飞去吗?你要是这样想,那就得好好看看路读君今天带来的这本书《聪明的鸟》吧。 看完这些补充的知识点,你会发现,其实鸟的聪明才智体现…

    2022-04-20 投稿
  • 长寿秘密被破解,怎样长寿的秘诀是什么

    天山童姥是金庸小说中的传奇人物,她能返老还童,古稀之年却宛若青春少女。这虽然有些诡异,但青春永驻是人类孜孜以求的梦想。《庄子·盗拓》言:人上寿者百岁,中寿八十,下寿六十。百岁人生是不少人心中美好的愿景。要长寿,更要健康长寿,科技迅猛发展的今天,越来越多的学者在寻找有效抗衰的路上汲汲求索。 长寿密码不断被破译 人体衰老可表现为皮肤皱褶、头发花白、行动迟缓以及多…

    投稿 2023-07-12
  • 优甲乐的副作用,长期吃优甲乐会有哪些副作用

    一、长期吃优甲乐,会有哪些副作用? 01 心血管的影响 优甲乐主要成分是左甲状腺素钠,主要适用于甲状腺功能减退的替代治疗,在甲状腺癌术后的抑制治疗,以及在用抗甲状腺药物治疗甲状腺功能亢进的过程中,可以用于辅助,如果服用过量对心脏产生不利的影响,左甲状腺素钠可以使得心脏心跳加快,也可以使得心肌收缩力加强。   如果心脏本身就存在着供血不足,由于优甲乐…

    投稿 2023-07-12
  • 怎么可以在网上赚钱(网上赚钱的路子)

        今天聊一些可以搞钱的兼职吧~   不一定有可行性,毕竟每个人的情况不一样。   但如果能给到大家一些启发和参考,也算是有用的。   01   我最近开始列我的购物清单,各种母婴产品罗列下来,要买的有一大堆。   像给宝宝准备的奶瓶,至少得两个,还要配加不同size的奶嘴。 &nbs…

    2022-01-20
  • 百度商城,百度app购物平台

    6月1日,苹果App Store页面显示,目前百度网盘App已无法从该应用商店搜索到,输入“百度网盘”仅能搜索到百度网盘青春版。据页面显示,百度网盘青春版由百度网盘打造,但5分的满分评分下,该APP只有1.4分。 而从已下载App处点击百度网盘,显示无法连接网络。对此,百度网盘官方微博回应称:目前已紧急沟通中,可先在百度App小程序端使用网盘。随后,百度网盘…

    2023-07-01
  • 沃派大流量卡(沃派流量卡15元)

    想要了解更多热门资讯、玩机技巧、数码评测、科普深扒,可以点击右上角关注我们的头条号:雷科技 ———————————- 小雷之前就一直在疯狂吐槽手机卡的销户问题 开卡的时候,营业厅的小姐姐都笑容满面 要销户的时候,就冷若冰霜了 “…

    2023-05-25 投稿
  • 电信正规纯流量卡免费申请(星卡大流量版套路)

      2022年顶级长期流量卡,星唐卡vs水仙卡,到底谁略胜一筹 如果让你选择,你会想要一张什么样的电话卡呢? 月租低的?流量多的?优惠期长的?能打电话的?还得是官方正规卡?靠谱一点,有售后的? 你要问这卡哪里找? 做你的流量管家,从此带你远离巨额话费,以及可怜通话与流量的多重折磨。 推荐官承诺只推官方正规手机卡,不做任何虚假宣传,对的起大家的信任。…

    2023-06-14
  • 流量购买网站(流量卡自助购买平台)

    随着物联网时代的到来,物联卡的出现给人们生活带来很大的变化。生活在其中,可能大家很难发现,但细细回想起来,会发现使用物联卡的智能设备为大家带来许多便利。比如:POS机的让交易变得简单,地磁车位检测器让停车变得智能,智能电水表节省人力,方便大家等等。物联卡凭借其强大的功能受到不少企业的青睐,但如何筛选靠谱的物联卡购买平台是个难以解决的难题。下面小编就简单说明一…

    2021-11-30
  • 网络推广团队需要哪些人手

    一个专业的营销团队都需要哪些人才?   随着市场竞争的日趋激烈,这种势头在未来将会越来越猛烈。通过分析市场营销行业我们发现,互联网技术的应用促进了电商平台的发展,市场营销模式发生了巨大的变化,对于市场营销人的需求也是越来越多。   互联网营销是一个新兴而热门的领域。在这个领域中人才的稀缺以及人才培养的滞后是企业网络营销工作的巨大障碍。其中…

    2021-11-13
  • 最火爆的网络游戏,梦幻西游现在哪个区最火

    说到网络游戏,在2023年我们能够看到最火爆的,分别是原神、三国志战略版、王者荣耀、和平精英等等手游。 如果把时间放到5年前的2018年,那会最火爆的游戏,则是王者荣耀、楚留香、FGO、皇室战争、天堂M等产品。 如果再往前5年,回到2013年,最火爆的游戏又是啥呢? 地下城与勇士、英雄联盟、我叫MT和部落冲突——在2013年那个手游刚兴起的时代,还有很多端游…

    2023-07-09