封装通用el-form表单(2种方式)

1、序言

         项目地址:git clone form-demo: 封装通用el-form

        一个后台管理系统最常见的是表单,表单最常见的是输入框、下拉选择、日期选择、单选、复选框等等, 系统添加若干模块,就复制粘贴若干个el-form、el-form-item,有一说一,完成需求快是快,但是代码冗余的部分太多了,能不能通过配置方式,自动生成el-form、el-form-item

        不封装代码前:

        封装代码后:

        两种封装方式的变量、方法名基本一致!

2、自定义组件方式封装el-form

        2.1、封装

        (1)新建commentForm文件夹,并创建index.vue文件

         (2)index.vue中

<template>
  <div>
    <el-form ref="form" :model="form" :rules="rules" :inline="inline" :label-width="labelWidth">
      <template v-for="(item, index) in formItemList">
        <!-- 输入框类型 -->
        <template v-if="item.type === 'input'">
          <el-form-item :label="item.label" :prop="item.model">
            <el-input v-model.trim="form[item.model]" :type="`${item.category || 'text'}`"
              :style="`width: ${item.width || '250px'}`" :clearable="item.clearable === undefined || item.clearable"
              filterable :placeholder="item.placeholder" />
          </el-form-item>
        </template>

        <!-- 下拉选择框 -->
        <template v-if="item.type === 'select'">
          <el-form-item :label="item.label" :prop="item.model">
            <el-select v-model.trim="form[item.model]" :style="`width:${item.width || '250px'}`" clearable
              :placeholder="item.placeholder || ''">
              <el-option v-for="(i, key) in  item.options" :key="i[item.value] || key" :label="i[item.label] || i.label"
                :value="i[item.value] || i.value">
              </el-option>
            </el-select>
          </el-form-item>
        </template>

        <!-- 日期选择器 -->
        <template v-if="item.type === 'date-picker'">
          <el-form-item :prop="item.model" :label="item.label">
            <el-date-picker v-model.trim="form[item.model]" type="daterange" range-separator="至" start-placeholder="开始日期"
              end-placeholder="结束日期">
            </el-date-picker>
          </el-form-item>
        </template>

        <!-- 开关 -->
        <template v-if="item.type === 'switch'">
          <el-form-item :prop="item.model" :label="item.label">
            <el-switch v-model="form[item.model]"></el-switch>
          </el-form-item>
        </template>

        <!-- 复选框 -->
        <template v-if="item.type === 'checkbox'">
          <el-form-item :prop="item.model" :label="item.label">
            <el-checkbox-group v-model="checkboxList">
              <el-checkbox :label="item.label" :key="index" v-for="(item, index) in item.options"></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
        </template>

        <!-- 单选框 -->
        <template v-if="item.type === 'radio'">
          <el-form-item :prop="item.model" :label="item.label">
            <el-radio-group v-model="form[item.model]">
              <el-radio :label="item.label" :key="index" v-for="(item, index) in item.options"></el-radio>
            </el-radio-group>
          </el-form-item>
        </template>

        <!-- 自己拓展... -->
      </template>

      <!-- 按钮列表 -->
      <el-form-item>
        <template v-for="item in buttonList">
          <el-button :type="item.type" @click="item.event">{{ item.text }}</el-button>
        </template>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  props: {
    // 生成el-form-item的数组
    formItemList: {
      type: Array,
      default: () => [],
    },
    // 是否行内表单模式
    inline: {
      type: Boolean,
      default: false,
    },
    // el-form-item的label宽度
    labelWidth: {
      type: String,
      default: '80px',
    },
    // 表单校验规则
    rules: {
      type: Object,
      default: () => { },
    },
    // 按钮列表
    buttonList: {
      type: Array,
      default: () => [],
    }
  },
  data() {
    return {
      form: {},
      checkboxList: [],
    }
  },
  methods: {
    // 返回经过校验的表单
    returnForm() {
      // 将复选框内容添加到form表单中,字段从formItemList type=checkbox中找model
      this.formItemList.forEach(item => {
        if (item.type == 'checkbox') {
          this.form[item.model] = this.checkboxList
        }
      })

      // 表单校验 
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.$emit('submitForm', this.form)
        }
      })
    },
    // 重置表单
    resetForm() {
      // 重置复选框
      this.checkboxList = []
      this.$refs.form.resetFields();
      this.$emit('resetForm');
    }
  }
}
</script>

<style scoped></style>

        (3)注意事项:

  •  el-checkbox中v-model绑定的值要事先存在,不然就会报出无法找到length属性的错误

            所以提前在data中声明一个数组,v-model绑定这个数组,返回表单给父组件时,将其添加到表单对象中,重置表单时,使这个数组为空即可实现重置表单功能!

  • 重置不成功的原因可能是:(1)未添加prop        (2)prop绑定的值与model绑定的对象所对应的属性不一致

        2.2、使用

重点关注部位:

(1)formItemList中的type决定生成什么类型的表单项,如输入框、下拉选项等等

(2)formItemList中的model表示表单项双向绑定的名称,也是子组件返回对象给父组件中对象的属性名

(3)formItemList中的options表示下拉选项、复选框、单选按钮的选项值

(4)@submitForm绑定的事件可以获取子组件返回给父组件经过校验的表单,通常不在子组件进行网络请求,让父组件进行网络请求

(5)父组件通过$refs获取组件实例从而调用子组件重置表单、提交表单的方法

<template>
  <div id="app">
    <CommonForm ref="form" :rules="rules" :buttonList="buttonList" :formItemList="formItemList" @submitForm="getForm">
    </CommonForm>
  </div>
</template>

<script>
import CommonForm from '@/components/commonForm'
import jsxForm from '@/components/jsxForm';
import JsxForm from '@/components/jsxForm'
export default {
  name: 'App',
  components: {
    CommonForm,
    JsxForm,
    jsxForm
  },
  data() {
    return {
      formItemList: [
        { label: '活动名称', type: 'input', model: 'name', placeholder: '请输入活动名称' },
        { label: '活动区域', type: 'select', model: 'region', placeholder: '请选择状态', options: [{ label: '上海', value: 'shanghai' }, { label: '北京', value: 'beijing' }] },
        { label: '活动时间', type: 'date-picker', model: 'startTime', },
        { label: '即时配送', type: 'switch', model: 'delivery' },
        { label: '活动性质', type: 'checkbox', model: 'type', options: [{ label: '美食/餐厅线上活动' }, { label: '地推活动' }, { label: '线下主题活动' }, { label: '单纯品牌曝光' },] },
        { label: '特殊资源', type: 'radio', model: 'resource', options: [{ label: '线上品牌商赞助' }, { label: '线下场地免费' }] },
      ],
      rules: {
        name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
      },
      buttonList: [
        { text: '提交', type: 'primary', event: this.submitForm },
        { text: '重置', event: this.resetForm },
      ]
    }
  },
  methods: {
    // 接受子组件传回来的form表单内容
    getForm(val) {
      console.log('val:', val);
    },
    // 点击提交,触发表单校验
    submitForm() {
      this.$refs.form.returnForm();
    },
    // 重置表单
    resetForm() {
      this.$refs.form.resetForm();
    }
  }
}
</script>

<style>
#app {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #2c3e50;

}
</style>

3、jsx方式封装el-form

jsx封装方式借鉴了这篇文章:element-ui 通用表单封装及VUE JSX应用 - 掘金

        3.1、封装

(1)上篇博客有简单介绍jsx:两种方式对el-table二次封装_码上编程的博客-CSDN博客

(2) 新建jsxForm文件夹,并创建index.js文件

(3)封装代码:

代码逻辑图如下:

export default {
  name: 'jsxForm',
  props: {
    // 生成el-form-item的数组
    formItemList: {
      type: Array,
      default: () => [],
    },
    // 是否行内表单模式
    inline: {
      type: Boolean,
      default: false,
    },
    // el-form-item的label宽度
    labelWidth: {
      type: String,
      default: '100px',
    },
    // 表单校验规则
    rules: {
      type: Object,
      default: () => { },
    },
    // 按钮列表
    buttonList: {
      type: Array,
      default: () => [],
    }
  },
  data() {
    return {
      form: {},
      checkboxList: []
    }
  },
  methods: {
    // 生成选项
    generateOption(itemObj) {
      let options = []
      for (let index = 0; index < itemObj.options.length; index++) {
        const item = itemObj.options[index]
        switch (itemObj.type) {
          // 下拉菜单
          case 'select':
            options.push(<el-option label={item.label} value={item.value}></el-option>)
            break
          // 多选框
          case 'checkbox':
            options.push(<el-checkbox label={item.label}></el-checkbox>)
            break
          // 单选框
          case 'radio':
            options.push(<el-radio label={item.label}>{item.label}</el-radio>)
            break
        }
      }
      return options
    },
    // 生成下拉菜单
    generateSelect(item) {
      return <el-select v-model={this.form[item.model]}>{this.generateOption(item)}</el-select>
    },
    // 生成多选框
    generateCheckbox(item) {
      this.form[item.model] = this.checkboxList
      return <el-checkbox-group v-model={this.checkboxList}>{this.generateOption(item)}</el-checkbox-group>
    },
    // 生成单选
    generateRadio(item) {
      return <div>
        <el-radio-group v-model={this.form[item.model]}>{this.generateOption(item)}</el-radio-group>
      </div>
    },
    // 生成输入框
    generateInput(item) {
      return (<div>
        <el-input v-model={this.form[item.model]} style={{ width: `${this.formItemContentWidth}` }}></el-input>
      </div>)
    },
    // 生成开关
    generateSwitch(item) {
      return <div>
        <el-switch v-model={this.form[item.model]}></el-switch>
      </div>
    },
    // 生成日期组件
    generateDate(item) {
      return <div>
        <el-date-picker v-model={this.form[item.model]} type={"daterange"} range-separator={"至"}
          start-placeholder={"开始日期"} end-placeholder={"结束日期"}>
        </el-date-picker>
      </div >
    },
    // 生成表单项
    generateFormItems(list = []) {
      let formItems = []
      list.forEach(item => {
        let formItemContent = ''
        switch (item.type) {
          // 下拉菜单
          case 'select':
            formItemContent = this.generateSelect(item)
            break
          // 单选框
          case 'radio':
            formItemContent = this.generateRadio(item)
            break
          // 输入框
          case 'input':
            formItemContent = this.generateInput(item)
            break;
          // 开关
          case 'switch':
            formItemContent = this.generateSwitch(item)
            break;
          // 日期
          case 'date-picker':
            formItemContent = this.generateDate(item)
            break;
          // 复选框
          case 'checkbox':
            formItemContent = this.generateCheckbox(item)
            break;
          default:
            break
        }
        formItems.push(<el-form-item label={item.label} prop={item.model}>{formItemContent}</el-form-item>)
      })
      return formItems
    },
    // 按钮列表
    generateBtnList() {
      let buttons = []

      this.buttonList?.forEach(item => {
        buttons.push(<el-button type={item.type} onClick={() => item.event()}>{item.text}</el-button>)
      })
      return buttons
    },
    // 重置表单
    resetForm() {
      // 重置复选框
      this.checkboxList = []
      this.$refs.form.resetFields();
    },

    // 返回经过校验的表单
    returnForm() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.$emit('submitForm', this.form)
        }
      })
    }
  },
  render() {
    return (
      <div>
        <el-form ref="form" props={{ model: this.form }} rules={this.rules} inline={this.inline} label-width={this.labelWidth || '150px'}>
          {this.generateFormItems(this.formItemList)}
          <el-form-item>
            {this.generateBtnList()}
          </el-form-item>
        </el-form>
      </div>
    )
  }
}

        3.2、使用

<template>
  <div id="app">
    <jsxForm ref="form" :buttonList="buttonList" :rules="rules" :formItemList="formItemList" @submitForm="getForm">
    </jsxForm>
  </div>
</template>

<script>
import jsxForm from '@/components/jsxForm';
export default {
  name: 'App',
  components: {
    JsxForm,
  },
  data() {
    return {
      formItemList: [
        { label: '活动名称', type: 'input', model: 'name', placeholder: '请输入活动名称' },
        { label: '活动区域', type: 'select', model: 'region', placeholder: '请选择状态', options: [{ label: '上海', value: 'shanghai' }, { label: '北京', value: 'beijing' }] },
        { label: '活动时间', type: 'date-picker', model: 'startTime', },
        { label: '即时配送', type: 'switch', model: 'delivery' },
        { label: '活动性质', type: 'checkbox', model: 'type', options: [{ label: '美食/餐厅线上活动' }, { label: '地推活动' }, { label: '线下主题活动' }, { label: '单纯品牌曝光' },] },
        { label: '特殊资源', type: 'radio', model: 'resource', options: [{ label: '线上品牌商赞助' }, { label: '线下场地免费' }] },
      ],
      rules: {
        name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
      },
      buttonList: [
        { text: '提交', type: 'primary', event: this.submitForm },
        { text: '重置', event: this.resetForm },
      ]
    }
  },
  methods: {
    // 接受子组件传回来的form表单内容
    getForm(val) {
      console.log('val:', val);
    },
    // 点击提交,触发表单校验
    submitForm() {
      this.$refs.form.returnForm();
    },
    // 重置表单
    resetForm() {
      this.$refs.form.resetForm();
    }
  }
}
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/12300.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

重学Java设计模式-行为型模式-责任链模式

重学Java设计模式-行为型模式-责任链模式 内容摘自&#xff1a;https://bugstack.cn/md/develop/design-pattern/2020-06-18-重学 Java 设计模式《实战责任链模式》.html#重学-java-设计模式-实战责任链模式「模拟618电商大促期间-项目上线流程多级负责人审批场景」 责任链模…

Shell 脚本编程

1. shell 概述 &#x1f95e; shell 是一个命令行解释器&#xff0c;它能接受应用程序、用户 的命令&#xff0c;然后调用操作系统内核。 ⭐ 还是一门 功能强大的编程语言&#xff0c;易编写、易调试、灵活性强。 2. shell入门 &#xff08;1&#xff09;脚本格式 &#x1f…

js中 = 等号赋值的问题,Js中对象的引用问题,深浅拷贝

js "" 赋值符号 在js中 “”对于基本数据类型是赋值符号&#xff0c;比较&#xff08; 或 &#xff09;的时候是值&#xff1b;对于引用数据类型-对象来说 是地址引用&#xff0c;比较的时候是比较的地址。 基本数据类型和引用数据类型的比较 let a 3; let b a;…

离散数学_九章:关系(1)

关系 9.1关系及其性质 1、二元关系 2、集合A上的关系 3、n元素集合 有多少个关系&#xff1f; 4、关系的性质 1. 自反 2. 对称 3. 反对称 4. 传递 5、关系的组合 关系的合成 关系的幂 9.1关系及其性质 1、二元关系 设A和B是集合&#xff0c;一个从 A 到 B 的二元关…

stm32当中GPIO输出知识点汇总(GPIO的八种模式及其原理)

一、GPIO工作模式. 1. 四种输入模式 GPIO_Mode_IN_FLOATING 浮空输入模式 GPIO_Mode_IPU 上拉输入模式 GPIO_Mode_IPD 下拉输入模式 GPIO_Mode_AIN 模拟输入模式 2. 四种输出模式 GPIO_Mode_Out_OD 开漏输出模式 GPIO_Mode_Out_PP 推挽输出模式 GPIO_Mod…

CentOS7-部署Tomcat并运行Jpress

1. 简述静态网页和动态网页的区别。 2. 简述 Webl.0 和 Web2.0 的区别。 3. 安装tomcat8&#xff0c;配置服务启动脚本&#xff0c;部署jpress应用。1、简述静态网页和动态网页的区别 静态网页&#xff1a; 请求响应信息&#xff0c;发给客户端进行处理&#xff0c;由浏览器进…

目标检测基础之IOU计算

目标检测基础之IOU计算 概念理解——什么是IOUdemo后记 概念理解——什么是IOU IOU 交并比&#xff08;Intersection over Union&#xff09;&#xff0c;从字面上很容易理解&#xff1a;计算交集在并集的比重。从网上截张图看看 I O U A ∩ B A ∪ B IOU \frac{A \cap B}…

基于BenchmarkSQL的Oracle数据库tpcc性能测试

基于BenchmarkSQL的Oracle数据库tpcc性能测试 安装BenchmarkSQL及其依赖安装软件依赖编译BenchmarkSQL BenchmarkSQL props文件配置数据库用户配置BenchmarkSQL压测装载测试数据TPC-C压测&#xff08;固定事务数量&#xff09;TPC-C压测&#xff08;固定时长&#xff09;生成测…

[ 云原生 | Docker ] 构建高可用性的 SQL Server:Docker 容器下的主从同步实现指南

文章目录 一、前言二、SQL Server 主从同步的原理介绍三、具体的搭建过程3.1 准备工作3.1.1 卸载旧版本&#xff08;如果有&#xff0c;可选&#xff0c;非必须&#xff09;3.1.2 安装 Docker3.1.3 验证本地 Docker 是否安装成功 3.2 创建 Docker 网络3.3 创建主从节点的 SQL S…

[Linux系统]系统安全及应用一

系统安全及应用 一、账号安全基本措施1.1系统账号清理1.1.1将非登录用户的shell设为/sbin/nologin1.1.2锁定长期不使用的账号1.1.3删除无用的账号1.1.4锁定账号文件文件chattr1.1.5查看文件校验和md5sum 1.2密码安全控制1.2.1设置密码有效期 1.3历史命令限制1.3.1 减少记录命令…

C语言笔记 | 一元三次方程

文章目录 0x00 前言 0x01 问题分析 0x02 代码设计 0x03 完整代码 0x04 运行效果 0x05 参考文献 0x06 总结 0x00 前言 在 1545 年&#xff0c;意大利学者卡丹所写的《关于代数的大法》中&#xff0c;提出了一元三次方程的求根公式。人们将其称为卡丹公式。对于标准型的一…

港科夜闻|国务院港澳办主任夏宝龙在香港科大考察期间,表示对学校开展创科工作的鼓励及希望...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、国务院港澳办主任夏宝龙在香港科大考察期间&#xff0c;表示对学校开展创科工作的鼓励及希望。考察期间&#xff0c;夏宝龙主任参观了香港科大的空气动力学和声学实验中心&#xff0c;以及香港科大先进显示与光电子技术国…

4个 Python 库来美化你的 Matplotlib 图表

Matplotlib是一个被广泛使用的Python数据可视化库&#xff0c;相信很多人都使用过。 但是有时候总会觉得&#xff0c;Matplotlib做出来的图表不是很好看、不美观。 今天我就给大家分享四个美化Matplotlib图表的Python库&#xff0c;它们可以轻松让你的Matplotlib图表变得好看…

( “树” 之 DFS) 404. 左叶子之和 ——【Leetcode每日一题】

404. 左叶子之和 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 示例 2: 输入: root [1]…

OpenGL入门教程之 深入理解

一、OpenGL简介 OpenGL是一种用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程规范。OpenGL包含一系列可以操作图形和图像的函数&#xff0c;但OpenGL没有实现这些函数&#xff0c;OpenGL仅规定每个函数应该如何执行以及其输出值(类似接口)&#xff0c;所以OpenGL仅是一…

基于JSP的网上购物系统的设计与实现(论文+源码)_kaic

摘 要 近些年来&#xff0c;社会的生产力和科技水平在不断提高&#xff0c;互联网技术也在不断更新升级&#xff0c;网络在人们的日常生活中扮演着一个重要角色&#xff0c;它极大地方便了人们的生活。为了让人们实现不用出门就能逛街购物&#xff0c;网络购物逐渐兴起慢慢变得…

新一代AI带来更大想象空间!上海将打造元宇宙超级场景!

引子 上海市经信委主任吴金城4月12日在“2023上海民生访谈”节目表示&#xff0c;上海将着力建设元宇宙智慧医院、前滩东体元宇宙、张江数字孪生未来之城等元宇宙超级场景。 吴金城说&#xff0c;新一代人工智能将带来更大的想象空间。比如&#xff0c;人工智能和元宇宙数字人的…

ESP32设备驱动-SHT20温湿度传感器驱动

SHT20温湿度传感器驱动 文章目录 SHT20温湿度传感器驱动1、SHT20介绍2、硬件准备3、软件准备4、驱动实现1、SHT20介绍 Sensirion 的 SHT20 湿度和温度传感器已成为外形尺寸和智能方面的行业标准:嵌入在 3 x 3mm 封装和 1.1mm 高度的可回流焊双扁平无引线 (DFN) 封装中,它提供…

项目人力资源管理

相关概念 组织结构图:用图形表示项目汇报关系。最常用的有层次结构图、矩阵图、文本格式的角色描述等3种。 任务分配矩阵(或称责任分配矩阵)(RAM):用来表示需要完成的工作由哪个团队成员负责的矩阵,或需要完成的工作与哪个团队成员有关的矩阵。 一、规划人力资源管理(编…

动力节点Vue笔记——Vue与Ajax

四、Vue与AJAX 4.1 回顾发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括&#xff1a; 原生方式&#xff0c;使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest()xhr.onreadystatechange function(){}xhr.open()xhr.send() 原生方式&#xff0…