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)

相关推荐

  • 简约昵称二字(二字小清新昵称)

    织霰 • 悱糜 野饨 • 沐庑 侍鎏 • 结庐 鹄谣 • 蔚滸 玖鸳 • 已畔 沬缨 • 靑迡 叙逆 • 妱玓 暖别 • 久箴 温珣 • 九澄 灼幽 • 酌麗 蘸笔 • 白髥 醨寻 • 鲽缶 衡辙 • 山栀 壹芳 • 温九 私奕 • 牧挽 訄樱 • 识辛 冷篠 • 食旖 甩墨 • 海言

    2021-11-27
  • 浙江省纪委书记(浙江省纪检委书记是谁)

    据浙江省纪委监委网站消息,10月1日,省委常委、省纪委书记傅明先赴党的诞生地——嘉兴南湖,瞻仰红船,重温“红船精神”,参观南湖革命纪念馆,看望节日期间坚守一线的干部职工,并调研了解清廉村居建设情况。 上述消息显示,傅明先已任浙江省委常委、纪委书记。 前几日消息,中共中央批准:傅明先同志不再担任山东省委常委、委员职务,另有任用。 傅明先,男,汉族,1964年1…

    投稿 2023-05-30
  • 网店联盟,网店联盟有限公司

    《网店联盟:探索电商合作的新模式》 在当今数字化的商业时代,网店联盟作为一种新兴的电商合作模式,正逐渐引起人们的关注和重视。 它可能像是电商领域的一座神秘桥梁,连接着各个独立的网店,为它们打开了更广阔的市场和发展空间。 那么,网店联盟究竟是什么?它又有哪些特点和优势呢?接下来,我们将深入探讨这个话题。 一、网店联盟的定义与构成 网店联盟,简单来说,就是由多个…

    投稿 2025-04-01
  • 在农村适合两个人做的小生意

    如果有人问您,现在农村做什么比较赚钱?我估计大多数人都会想到搞农家乐、农村旅游、搞大规模种养项目等等,我不否认这些项目确实很赚钱,但是在农村有一些不起眼的小项目,只要做好了同样也是能赚大钱的,比如今天我要给大家分享的回收项目就是如此。 回收项目,大多数人认为这就是收破烂的,这类项目又脏又累,稍微有点本事的人都是不会去做这类项目的,只有那些老头、或者没有上进心…

    2022-06-08 创业项目
  • 胡来的故事

    再遂平县长大的人,基本上都知道一句类似歇后语的话:遂平县的县官—胡来。意思是一个人做事不讲理,不讲法,有点胡作非为的意思。 这句话来源于河南豫剧《李天宝吊孝》。里面一个贪财的县官就叫胡来。故事梗概:明末清初,河南遂平县一富户张忠实为高攀大富李家,把大女儿凤姐许配给李家公子李天保。几年后,李家父母双亡,家业被焚,张忠实有意赖婚,谎称凤姐暴病身亡。李…

    投稿 2023-05-23
  • 褚时健的传奇人生简介(褚时健传奇的一生)

    “生命中最伟大的时刻不在于永不坠落,而在于坠落之后总能再度升起。” 3月5日13时20分,曾经的“中国烟草大王”、云南冰糖橙品牌“褚橙”创始人褚时健去世,享年91岁。很多人用南非传奇曼德拉的这句名言,来形容褚时健的传奇一生。 1979年,褚时健进入位于云南省的玉溪烟厂任职厂长,把一家不起眼的小厂在短短十余年的时间里发展成年税利达到206亿元的大企业。1999…

    2022-04-27
  • 什么浏览器能看蜜芽贴吧

    近期,打出“淘海外正品”口号的洋码头却因密集的用户投诉而再次陷入假货风波。 继抖音大V“大狼狗郑建鹏&言真夫妇”针对用户反映在其直播间购买的洋码头产品存在质量问题而道歉后,近期有大批用户在公开投诉平台对洋码头提出了售假质疑,认为该平台缺乏对商品品质及买手的严格监管,导致其正品承诺成为空谈。 艾媒咨询分析师认为,正品问题一直是跨境电商行业的痛点,加强正…

    2022-01-22
  • 拼多多三只松鼠,拼多多三只松鼠是正品吗

    《拼多多三只松鼠:电商界的独特存在》 在如今竞争激烈的电商市场中,拼多多三只松鼠无疑是一个备受关注的存在。 它仿佛是电商领域的一颗璀璨明星,吸引着众多消费者的目光。 那么,拼多多三只松鼠到底有何独特之处呢?让我们一起来深入探究。 一、品牌定位与特色 三只松鼠,这个名字一听就给人一种可爱、亲切的感觉。 它仿佛是一个在森林中穿梭的小精灵,带着满满的活力和趣味。 …

    投稿 2025-02-23
  • 免费的优质网站(网络营销优质的工具网站)

    1、小纸条 在阿里云盘以不限速号称逐渐成为主流网盘后,收藏和分享阿里云盘资源的站点也越来越多,不甚新鲜。不过大多都是以做一个索引功能类的功能,也有像【小纸条】这样子把目前各类阿里云资源一一分类,包括影视、动漫、软件、小说等分类,哈哈,就怕你的阿里云盘空间不够。 2、抖音/Tiktok无水印解析 【抖音/Tiktok无水印解析】站点,将抖音/Tiktok的链接…

    2022-05-22 投稿
  • 公众号付费阅读,个人公众号怎么开通付费功能

    帮朋友开通了一个知识付费公众号,用的还是自己的系统。、 首先开通好使用企业资质认证的服务号,并且设置好基础的信息。如首次关注的默认回复语 还有出现问题时,通过企业微信来联系客服解决等等。   公众号对接好后,我们接下来打开【线上课堂】,来看看 知识付费系统上线后的效果,里面的设计也是我本人来提供指导的。简单上些图给各位参考下。   &nb…

    2021-11-21 投稿
  • 花开花落自有时,如懿说的花开花落自有时含义

    雨终于停了,依然没有太阳。 不知道想说点什么,却有点欲说无语的感觉。可心里分明有一种难以表达的东西在涌动,而此刻自己却是不知道怎么表达,如向子期所言,刚开头却又煞了尾。浓浓的喜悦中分明也有一丝的淡淡的失落,却又说不出为什么,当你所有的一切都要化上句号时,也许这中感觉会不经意的爬上心头,钻进心里。然而我分明感到自己忽然之间轻松了好多,是对牵挂的一种释然,当你真…

    2022-05-02
  • 如何赚钱农业发家致富,农业怎样致富

    农村搞种植就像经商一样,有赚钱的也有不赚钱的,有的守着几十亩地,一年到头也赚不了几个钱,有的只有几亩地,一年收入十几万却很轻松,而有的靠承包别人的土地一年收入几十万、上百万的也大有人在,赔钱的也不在少数。搞农业种植不容易,关键看你怎么干,下面四个农业种植的真实案例会让你明白,你做对了吗? 案例一 夫妻俩种植木耳菜,一年种两茬,五亩地收入6万元 这是笔者邻村的…

    2022-04-24 创业项目