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)

相关推荐

  • 最容易学的才艺表演(晚会节目简单创意)

    初一,不少卫视春晚接续登场,为观众们呈上了丰富多彩的节目盛宴。今年各家卫视都打出了特色牌,北京台春晚玩转跨界,江苏卫视春晚打足情怀牌,东方卫视春晚发挥热剧热综的海上风情,辽宁卫视和天津卫视春晚则继续在语言类节目上。值得一提的是,今年还有几家卫视春晚独辟蹊径,比如以古风意外出圈的河南卫视春晚、首次打出“喜剧春晚”主题的浙江卫视春晚,全新的参与方式带来了更多惊喜…

    2022-01-07
  • 手机版数字组合生成器,数字排列组合生成器手机版

    将6个数2、0、1、9、19、20按任意顺序排成一行,拼成一个8位数(首位不为0),则产生的不同的8位数的个数有多少个?(2019年全国高中数学联赛A卷)(自评难度3) 6个数对应6个位置,当2后接0,1后接9,形成的数会重复。易想到用容斥原理,总个数-20重复的数-19重复的数+19、20同时重复的数。 (1)把6个数当成6个不同(含有0)的数,总数为6!…

    投稿 2022-03-22
  • 穿透力强的路由器,无线路由器的穿墙效果

    「辰鸿科普」相信很多用户在购买无线路由器的时候都会考虑到它的穿墙能力。毕竟绝大多数用户家里的布局都不是大通间,多少都会有那么几堵墙的。市面上很多无线路由器也都宣称自己有着很强的穿墙效果,并且列出了很多参数,那么无线路由器的穿墙能力到底如何去辨别呢?下面电脑配置网小编就来为大家介绍一下辨别无线路由器穿墙能力的相关知识,避免小白入坑。 小白们在选购无线路由器的时…

    2023-02-02 投稿
  • 感叹号图标,带感叹号的故障灯图标

    电脑无法上网,右下角网络图标上有个感叹号! 是不是很多人都,遇到这个问题了——-电脑右下角感叹号! 这个问题是不是让您很烦恼,要紧要忙的时候,电脑上不了网,生气起来真的想砸电脑。 第一个引起感叹号的原因: 1、查看电脑网卡是不是被配置了错误的静态IP地址。在控制面板\网络和 Internet\网络连接。 2、找到本地连接。 3、右击本…

    2023-06-29
  • 微信手机号换了怎么办(如何更换已换微信手机号的账号)

    我们大部分小伙伴们都在使用微信,都用手机绑定了微信号。可是有时候我们的手机丢了,或者我们换了手机,那么微信就比较麻烦啦。那么微信绑定手机号码换了怎么办?下面小编就为小伙伴们介绍微信换手机号验证几种解决方法,一起来看看吧 方法一:通过申诉找回 1、在微信未登录界面选择红色方框中的”找回密码“功能。 2、点击选择“找回微信账号 密码”。 3、出现的微信账号密码找…

    投稿 2023-05-23
  • 潮牌服装进货渠道(时尚服装批发商进货渠道)

    眼下正是服装开店的旺季,很多新手都想趁着秋冬销售旺季来临之前把新店开起来,能抓住一波旺季让店铺业绩好起来。而新手创业开服装店由于经验上没有其他老板那么足,所以在货品上就要上心,找到一批有销售优势的货品能够为店铺带来业绩。那新手开服装店去哪里进货呢?第一次服装进货要注意哪些问题呢?今天我们就来看看吧。 新手开服装店进货去哪里 新手服装进货渠道有哪些?   一、…

    2021-12-02
  • 已婚渣男最怕什么报复,怎么报复已婚渣男最好

    我们生活的重心永远都应该放在自己身上,但是在现代中很多重感情的人都容易不理智地做出很多感性行为。 “渣男”这个词在我们生活中并不陌生,甚至最近的某音都在流行一段视频“选择男性的时候,放着有钱有车有房的人都不选,独独选中渣男。”来自嘲自己的感情经历和宣泄自己的情绪。 很多认真的人在感情中受到伤害后,大部分人会开始伤心难过,接着就开始质疑自己,自怨自艾,接着就说…

    2022-03-17 投稿
  • 寿险公司排行榜全国(寿险公司最新排名)

    2021年 已经过去了21天 各家寿险公司 都铆足了劲的冲击“开门红” 作为保险公司的前线 省级分公司 谁家规模最大呢? 1 寿险省级分公司大排名 谁能入围500强? 截至2019年末,我国共有90家寿险公司,省级分公司约1165家。 从总公司的角度,去看寿险公司的规模排名,之前我们有分析过。 今天,我们带大家下探一级,看看1165家省级寿险分公司的保费大排…

    2022-01-25 投稿
  • 网址缩短生成短链接(短网址生成)

    短网址除了能缩短网址之外,还有很多功能,像是缩址后的短链接,可以追踪活动成效!不过缩短链接工具这么多,要如何选择合适的缩短网址工具呢?本篇分享7大缩址推荐工具,一定有符合你的需求的! 本文节选自2022年SKUKING跨境电商数字化赋能沙龙撷英分享,根据SKUKING跨境电商研究中心编辑整理。 粉丝朋友可以「点击头像,进入主页」查看往期内容中SKUKING的…

    2023-01-31 投稿
  • 2021有效实名认证大全(2021最新实名认证)

    建议网络游戏开启实名制人脸识别”“建议未成年人网游每30分钟刷一次脸”“建议禁止明星代言网游”……今年两会期间,未成年人游戏相关话题成为部分代表委员关注的焦点。 在这背后,未成年人沉迷游戏、退款难等痼疾难解。3月17日,《中国经营报》记者在“黑猫投诉”平台检索发现,与“游戏”相关的投诉话题多达134447条,涉及“未成年人游戏”的搜索结果是6351条。《黑猫…

    投稿 2022-02-20
  • 2021年退休工资计算公式,2021年企业退休工资计算方法

    很多老人辛辛苦苦地忙碌了一辈子,最期盼的事情就是退休以后可以安安稳稳的领养老金了。可是养老金究竟怎么算呢? 说实话,退休养老金的计算国家是有固定的公式的。一般来讲,企业退休人员的养老金计算公式主要包括基础养老金、个人账户养老金、过渡性养老金三部分构成。 其中,基础养老金、个人账户养老金计算公式是2005年国发38号文件规定的。同时按照这个文件规定,各省市可以…

    2022-03-15
  • nagios安装,nagios安装与配置

    《Nagios安装全攻略》 一、准备工作 在开始安装Nagios之前,我们需要做一些准备工作。也许你会想,为什么要做这些准备呢?这就好像盖房子之前要先准备好砖头、水泥一样,是为了确保后续的安装过程能够顺利进行。 我们需要确保服务器的操作系统是支持Nagios的,比如Linux系统(如CentOS、Ubuntu等)。不同的操作系统在安装过程中可能会有一些差异,…

    2025-12-02