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)

相关推荐

  • 卸载精灵,康佳电视怎样下载电视管家

    当前电视中常常会出现一些流氓软件,那么如何才能摆脱流氓软件的困扰呢?KONKA电视管家是一款非常简单的电视端安装和卸载应用的内置程序,具有一键加速,应用管理,安装包管理,网络测速,开机直达五大功能。升级版中还添加了白名单管理、自启动管理。 新增功能一:自启动管理 在自启动中,只要将流氓软件禁止自启动,即可完成。 新功能二:白名单管理 设置白名单,将在优化清理…

    2023-07-01
  • g630 cpu参数,英特尔g630cpu参数

    中国国内芯片制造商 兆芯 为 KX-6000G CPU 准备了 1.5 TFLOP 集成 GPU,其速度与 NVIDIA 的 GT 630 相当中国国内芯片制造商兆芯正在以他们的第一款产品进入APU领域,KX-6000G 处理器,提供高达 1.5 TFLOP 的 GPU 算力。兆芯的下一代KX-6000 CPU阵容将取代2017-2018年上市的KX-500…

    2023-07-12
  • 促销技巧和方法(常见的促销技巧有哪些)

    促销是终端店铺最常用的营销方式之一,有效的促销方式不仅可以刺激阶段内销售,同时也有助于扩大品牌市场占有率以及影响力,今天的推文,小编总结了门店最常用10大促销方式,供大家参考; 一、返现 返现,也称满送,即促销时规定买满多少金额,现场返还现金多少,比如买满300元返30元,即9折。这种促销商场使用频率相对高一些,因为是直接用现金返还,吸引力较大。 注意点:返…

    2021-12-14
  • 奔驰级别档次怎么分(奔驰最好级别是什么级)

    世界上本来没有豪车,因为有钱人变多了,才有了豪车 豪车,显然是为了有钱人准备的。放在10年前,就算是奥迪A4L也是妥妥的豪车。但是现在看,很多人认为奥迪A4L可能都不属于豪车行列。 那么到底什么车才能算是豪车?毕竟有的人可能会说40万的奔驰也算奔驰? 从目前行业标准看,起售价高于30万就会纳入豪车行列。当然如果你是保时捷车主你可能不会这么认为,但是从汽车销量…

    2022-05-08 投稿
  • 抖音闪退,抖音闪退OPPOA9

    《抖音闪退问题探究:原因、影响及解决办法》 一、引言 在当今的移动互联网时代,抖音作为一款极具影响力的短视频应用,深受广大用户的喜爱。 然而,不少用户在使用抖音时可能会遇到闪退的问题,这不仅给用户带来了不便,也可能影响到用户对抖音的使用体验和满意度。 那么,抖音闪退究竟是由哪些原因引起的呢?它又会对用户产生哪些影响呢?我们又该如何解决这个问题呢?接下来,让我…

    2025-06-15
  • 手绘时间轴怎么做漂亮(手绘时间轴怎么做漂亮精致)

    很多手帐小白会问,我想学手帐,怎么入门呀? 那么多漂亮的本子,我怎么选呀? 我不会画画,能做出好看的手帐吗? 手帐小白入门一点不困难,只要做到以下几点。 一、学手帐的初心 先问自己为什么想学手帐?觉得手帐大神的作品漂亮?想提高时间管理?想获得开挂的人生?想实现自己的梦想?学手帐的目的不同,行动不同。这个问题很重要,一定要思考好。 可能小白会说,我也不知道为什…

    2023-05-25
  • 经营停车场赚钱,停车场干什么能赚钱

    智慧停车被行业认为是破解城市停车难问题的关键钥匙,目前智慧停车市场主要有两种发展方向,一种是自下而上的发展模式,另一种是自上而下的发展模式。 第一种是完全市场化,由停车运营公司自己去开发一家家的停车场,然后形成自己的片区,它们分别从增加泊位建设和提升停车效率出发,对缓解停车难问题有所帮助。对应的企业类型分别是视频识别厂商、停车AGV厂商以及立体车库厂商,但这…

    2023-01-31
  • 不会游泳可以考游艇证吗(游艇驾照怎么考)

    “船舶游艇驾照”称为船员适任证书,依船吨位大小,分为不同的**。只有持有适任证书的,方能驾驶船舶。这一点,与汽车驾照类似,分为不同的准驾证。三亚海事局透露,三亚持有适任证书的人不足千人。 依即将实施的《中华人民共和国船员条例》,申请船员适任证书,应当向海事部门提出书面申请,并附送相关证明材料,通过海事部门组织的船员任职考试后才能发放。而且,法律规定,年龄在1…

    2022-01-04
  • 明朝海瑞介绍,清官海瑞的故事

    海瑞(公元1514-1587),字汝贤,海南琼山县人。他生活在明王朝由盛及衰的转折时期,表面一片升平,实则危机四伏。 海瑞年青时,便对社会问题表现了极大的关注。他在户部供职时,出于对国家财力的忧虑,为进谏迷信道教、一心求仙而纵容各地大兴土木修建庙坛道观的嘉靖帝,以六品小官身份抱着必死决心毅然上疏。这次他呈上的奏疏便是有名的“直言天下第一事疏”,后人称为《治安…

    2023-07-04
  • 短信跟踪,短信跟踪定位

    《关于短信跟踪的探索与思考》 一、短信跟踪的概念与原理 也许在很多人看来,短信跟踪是一个比较神秘的领域,它到底是指什么呢?我觉得短信跟踪可能就是通过一些技术手段,来获取关于短信的相关信息,比如短信的发送者、接收者、发送时间、内容等等。 就好像我们在生活中,有时候会通过一些线索来追踪一个人的行踪一样,短信跟踪也是在试图通过短信这个线索来了解一些事情。它的原理也…

    2025-10-05
  • 儿童多动症核心特征,判断儿童多动症的标准

    多动症(ADHD)是一种常见的儿童神经发育障碍,其主要特征包括注意力不集中、过度活跃和冲动行为。以下是多动症孩子可能呈现的一些症状表现: 1. 注意力不集中: – 不能长时间保持对任务或活动的关注。 – 容易分心,难以专注完成学校作业或其他任务。 – 经常忘记细节,失去物品或忘记完成日常任务。 2. 过度活跃: &#821…

    2023-07-04
  • 强行删除文件,cmd命令强制删除文件

    《关于强行删除文件的那些事儿》 一、强行删除文件的常见方式及原理 在计算机操作中,强行删除文件的方式有多种,也许最常见的就是直接右键点击文件并选择“删除”选项,然后在弹出的确认对话框中点击“确定”。这种方式背后的原理,我觉得可能是操作系统将被删除文件的相关信息标记为可删除状态,然后在适当的时候将其从存储介质中清除。 还有一种方式是使用命令行工具,比如在Win…

    2025-10-14