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)

相关推荐

  • 抖音短视频运营方案(短视频矩阵化运营策略)

    融媒宝是一款自媒体多平台账号管理工具,一键管理多个自媒体平台,公众号、订阅号、短视频号、头条号等都可以一键管理。可以将图文、视频一键分发上传至30+自媒体、短视频平台。 抖音短视频批量运营,大佬都是这样搭建自己的短视频矩阵的,现在的短视频这么火,好多朋友都不知道有什么好的短视频矩阵。 今天我就给大家介绍一下运营的相关知识,先给大家介绍一下什么是短视频矩阵,运…

    2023-05-29
  • 怎么提高B站播放量,一文告诉你B站的流量逻辑,

    短视频的流量之大,但是在所有的自媒体渠道中,相同粉丝数的红人中,短视频的红人是不怎么值钱的(头部账号除外),很多抖音网红大火之后,还不知道怎么变现就已经在平台在消失,因为你背后没有团队,你接广告难、拍摄难。流量难。 批量做账号售卖、为其他平台导流、做电商赚取佣金、开直播变现成为了短视频平台营销的重要变现渠道(感觉现在很多短视频平台慢慢变成了营销机构牟利的工具…

    2022-05-04
  • 尺度大的言情小说(超级言情小说)

    今天要介绍的几部美剧都是因为“尺度过大、污到没边”而在网络上销声匿迹的。 推给大家是为了让大家避雷,如果不慎获得了资源,一定要及时删除,以免对自己的身心造成不良影响。 加州靡情(Californication) 直接打中文剧名是冒了一定风险的,一般国内都叫他“加州迷情”。 从中文译名就能看出这部剧是多么的“生猛”。 一部“喜剧”,播放于2007年到2014年…

    2023-05-31 投稿
  • 火棉胶婴儿是什么导致的?火棉胶婴儿新生儿鱼鳞病

    全家满心欢喜等待宝宝降临,可生下来后医生却说必须马上转入NICU(新生儿重症监护室)!张女士(化名)和家人听到这个消息后心情跌到谷底,她的宝宝文文(化名)被诊断为罕见病——“火胶棉婴儿”!隔着暖箱看一眼宝宝,张女士的眼泪再也绷不住了…… 图片来源:视觉中国 全身像裹着一层羊皮纸 多处皮肤褶皱破损、断裂 文文一出生,就与其他宝宝不同,脸上及四肢的皮肤都“油光光…

    2022-04-19
  • 国美店庆,国美店庆:最低价商品疯狂抢购

    随着消费全面升级和主要消费人群的代际变迁,消费者愈发追求多元化、个性化、智能化的高端品质商品,也更倾向于选择能提供更高效率、一次性成套购买的商家平台。年末正是大小家电囤货的集中时期,广州国美积极迎合消费者升级需求,于11月30日-12月1日开展年终“超级福利日”专场活动,从整套购买优惠到单品爆款打造,都致力于为消费者提供高品质低价格、一站式的完善服务。 广州…

    投稿 2023-05-15
  • 多头管理怎么解决(多头注册行为怎么解决)

    东京奥运会后,全红婵等奥运健儿的姓名被多方申请抢注为商标。8月18日,中国奥委会对此发声,喊话停止“恶意抢注商标”的行为。8月19日,国家知识产权局官网发布通告,对“杨倩”“陈梦”“全红婵”等109件商标注册申请予以驳回。   什么叫恶意抢注?8月23日,山西晚报记者对此进行了采访。 商家蹭热度 抢注奥运健儿姓名 从国家知识产权局驳回的名单中可以发…

    2021-11-10
  • 袁隆平的故事概括 袁隆平是如何实现植物抗性育种的

    阳光、沙滩、椰林……我国北纬18°区域内的海南三亚等地,由于坐拥得天独厚的气候条件,早已成为闻名遐迩的旅游度假胜地。 然而,在这片热土上,一群南繁育种科研工作者追光逐梦的故事却少为人知。2020年底至今,记者7次深入南繁基地,在田间地头与这些默默无闻、埋头苦干的南繁人深度接触,发现他们不仅托起“中国饭碗”的坚实底座,还在精神高地上立起丰碑。 从袁隆平发现神奇…

    投稿 2023-06-03
  • 淘宝搜索指数是什么意思(淘宝搜索指数查询)

    随着电商市场的竞争越来越大,很多电商运营者都在不断开拓新思路去推广。例如会思考到底哪些词会比较多人搜索,放在自家商品标题上面,会不会被买家搜索看到。能不能被搜索到,这就要看自己店铺商品的竞争力强不强了。所以我们要时刻关心商品的排名,在推广的时候,做到针对性优化,提高商品的竞争力和曝光率。今天为大家分享的淘宝经验是:淘宝商品关键词排名查询。关键词定位到排名,就…

    2021-12-22 投稿
  • 篮球鞋推荐,篮球鞋推荐1000左右

    选对篮球鞋很重要,既要考虑颜值、性能还得看品牌。随着国潮的蓬勃发展,不少国产运动品牌的篮球鞋也做得不错,比如李宁、安踏、361°等,便宜又好看,和国际大牌比毫不逊色。 李宁樱花粉音速9篮球鞋 李宁的音速9系列篮球鞋颜值和性价比都很不错,尤其是这款樱花粉配色,日常休闲或打比赛都能穿,绝对是“性价比之王”。经典的低帮鞋型穿着舒适有型,中底搭载LIGHT FOAM…

    2022-05-03 投稿
  • 1000浏览量多少赞可以上热门?

    首先我们来看一下叠加推荐原理。当我们发布新视频的时候,抖音系统会给这个视频匹配一些冷启动流量。那么冷启动流量的大小,在我们上节课流量池中有详细讲解过。不懂的同学可以看一下上节课程,经过冷启动流量的筛选,如果视频数据反馈较好的话,会进入下一个更大的流量池,那么视频数据怎样算是比较好的,第一点赞率在百分之0.3以上,也就是说1000个播放量,有30个以上的点赞,…

    2023-02-18
  • 公司网站怎么建立,如何使用领英做外贸

    B2B公司一直在寻找与竞争对手区分的方法。越来越多的公司使用社交媒体渠道与目标受众联系,其中一个备受欢迎的渠道是领英。 这个专业的社交网站已成为人们寻找工作和建立关系的场所。因此,不足为奇的是,超过一半(52%)的B2B营销人员表示,领英在客户获取策略中至关重要。 但如果您尚未将领英纳入您的营销组合中,那么现在可能是时候开始了。在此,我们将介绍什么是领英公司…

    2023-06-30 投稿
  • 开网站靠什么赚钱(如何建立自己的网站赚钱)

    这个问题很有意思,作为一个曾经一年做出10万日IP和两年通过网站赚到100W的站长,我来聊聊这个问题。 按照我的步骤来,一个个思考并解决,可以做出一个让你赚钱的网站。 我们不聊不能通过网站直接或者间接赚钱的网站,仅谈怎么建站赚钱。 在做网站开始之前,我们先要思考几个问题? 一、我们赚什么钱? 二、网站规划 三、怎么建站? 四、怎么做好网站? 明白了自己要赚什…

    2021-11-12