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

这篇具有很好参考价值的文章主要介绍了封装通用el-form表单(2种方式)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、序言

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

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

        不封装代码前:

封装el-form,前端,vue.js,前端,javascript,elementui

        封装代码后:

封装el-form,前端,vue.js,前端,javascript,elementui

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

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

        2.1、封装

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

封装el-form,前端,vue.js,前端,javascript,elementui

         (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="form[item.model]">
              <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>
  </div>
</template>

<script>
export default {
  props: {
    form: {
      type: Object,
      default: () => { }
    },
    // 生成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: () => { },
    },
  },
  data() {
    return {
    }
  },
  methods: {
    // 返回经过校验的表单
    returnForm() {
      // 表单校验 
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.$emit('getForm', this.form)
        }
      })
    },
    // 重置表单
    resetForm() {
      // 重置复选框
      this.$refs.form.resetFields();
    }
  }
}
</script>

<style scoped></style>

        (3)注意事项:

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

封装el-form,前端,vue.js,前端,javascript,elementui

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

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

        2.2、使用

重点关注部位:

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

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

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

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

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

<template>
  <div id="app">
    <CommonForm ref="form" :form="form" :rules="rules" :formItemList="formItemList" @getForm="getForm">
    </CommonForm>
    <el-row>
      <el-button type="primary" @click="submitForm">提交</el-button>
      <el-button @click="resetForm">重置</el-button>
    </el-row>
  </div>
</template>

<script>
import CommonForm from '@/components/commonForm'
export default {
  name: 'App',
  components: {
    CommonForm,
  },
  data() {
    return {
      form: {},
      editForm: {
        name: '张三',
        region: 'shanghai',
        delivery: true,
        resource: '线上品牌商赞助',
        startTime: [
          '2023-05-10',
          '2023-05-11'
        ],
        types: '线下主题活动',
      },
      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', modelString: 'types', options: [{ label: '美食/餐厅线上活动' }, { label: '地推活动' }, { label: '线下主题活动' }, { label: '单纯品牌曝光' },] },
        { label: '特殊资源', type: 'radio', model: 'resource', options: [{ label: '线上品牌商赞助' }, { label: '线下场地免费' }] },
      ],
      rules: {
        name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
      }
    }
  },
  created() {
    // 表单初始化
    this.formInit()
  },
  methods: {
    // 表单初始化
    formInit() {
      this.form = JSON.stringify(this.editForm) ? this.editForm : {}

      // checkbox类型的组件需要初始化数组
      this.formItemList.forEach(item => {
        if (['checkbox'].includes(item.type)) {
          if (!this.form[item.modelString]) {
            this.$set(this.form, item.model, [])
          } else {
            this.$set(this.form, item.model, this.form[item.modelString]?.split(','))
          }
        }
      })
    },
    // 接受子组件传回来的form表单内容
    getForm(val) {
      this.formItemList.forEach(item => {
        // 
        if (['checkbox'].includes(item.type)) {
          if (this.form[item.model] && this.form[item.model]?.length != 0) {
            val[item.modelString] = val[item.model]?.join(',')
          }
        }
      })
      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>

        2.3、回显数据

        准备一个对象:editForm 模拟form已经有了数据,对editForm进行非空判断,如果有值则将其赋值给form,无值则赋值{}

this.form = JSON.stringify(this.editForm) ? this.editForm : {}

        刚刚说过elementUIcheckbox使用v-model绑定的值需要为真实存在的数组,若在form组件额外实例化一个变量专门处理checkbox显得不那么智能化封装el-form,前端,vue.js,前端,javascript,elementui 

        如何做到传一个{}对象给form组件,不报上述错误,并且还能回显数据,这就要在引用form组件的组件进行一下对象的初始化了

        (1)像elementuicheckbox复选框、Cascader 级联选择器、日期组件等等v-model绑定的是数组,而有时候后端接口文档不是数组,需要你手动处理,打个比方:

        前端将多个选中的值(这些值存在数组)使用字符串形式且里面的值用逗号隔开,比如:

[1, 2, 3, 4]  =>  "1,2,3,4",这样传给后端,后端返回“1,2,3,4”,要求你能转化成数组[1,2,3,4]渲染到elementui组件。

split(','):将字符串中逗号分隔的元素转成数组,[1, 2, 3, 4]  =>  "1,2,3,4"

join(','):将数组元素转成逗号分隔的字符串,   "1,2,3,4" =>  [1, 2, 3, 4]

$set(数组/对象,property/索引,具体值)vue2中使用Object.defineProperty监听响应式变化,对数组和对象的监听不是那么友好,很多时候数据变化了但是视图没发生变化,$set的出现解决了这个问题

 // 表单初始化
    formInit() {
      this.form = JSON.stringify(this.editForm) ? this.editForm : {}

      // checkbox类型的组件需要初始化数组
      this.formItemList.forEach(item => {
        if (['checkbox'].includes(item.type)) {
          if (!this.form[item.modelString]) {
            this.$set(this.form, item.model, [])
          } else {
            this.$set(this.form, item.model, this.form[item.modelString]?.split(','))
          }
        }
      })
    }
 // 接受子组件传回来的form表单内容
    getForm(val) {
      this.formItemList.forEach(item => {
        // 
        if (['checkbox'].includes(item.type)) {
          if (this.form[item.model] && this.form[item.model]?.length != 0) {
            val[item.modelString] = val[item.model]?.join(',')
          }
        }
      })
      console.log('val:', val);
      // 此处可以请求后台了
    },

3、jsx方式封装el-form

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

        3.1、封装

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

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

(3)封装代码:

代码逻辑图如下:

封装el-form,前端,vue.js,前端,javascript,elementui文章来源地址https://www.toymoban.com/news/detail-704108.html

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>

到了这里,关于封装通用el-form表单(2种方式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3使用el-form实现登录、注册功能,且进行表单验证(Element Plus中的el-form)

    简介:Element Plus 中的 el-form 是一个表单组件,用于快速构建表单并进行数据校验。它提供了丰富的表单元素和验证规则,使表单开发变得更加简单和高效。可以搭配el-dialog实现当前页面的登录、注册页 ,这两天在vue3中用到了表单登录,特意记录一下,这里没有封装,直接使

    2024年02月07日
    浏览(63)
  • el-form与el-upload结合上传带附件的表单数据(前端篇)

    本文前端采用Vue + element-plus技术栈,前端项目参考yudao-ui-admin-vue3项目与 Geeker-Admin项目。 这篇文章是el-form与el-upload结合上传带附件的表单数据(后端篇)-CSDN博客姐妹篇,后端篇文章主要讲的是后端的实现逻辑,前端篇稍微简单一些,其实最主要的就是封装el-upload组件,供具

    2024年01月22日
    浏览(42)
  • Vue - Element el-form 表单对象多层嵌套校验

    针对el-form的数据源是对象嵌套对象,在进行数据绑定和校验时和单层的对象有一点区别, 具体是下面两部分: 数据源: 1、 给 el-form-item 的 prop 设为: prop=\\\"health.height\\\" 。 v-model 设为: v-model=\\\"fromData.health.height\\\" 2、校验规则 rules 对象对应的key设置为数据源内部的值: \\\'health.heig

    2024年02月14日
    浏览(51)
  • el-form 动态表单增减项 (vue+element ui)

    1、点击”+“,弹出弹窗,新增一项,点击”-“,删除当前项 代码展示: html代码: 注意: el-form-item(表单项)循环,绑定的数组写在form当中 表单: 新增参数弹框: data: methods: 1、点击新增,弹出新增弹窗,添加表单项 2、点击”-“,删除当前表单项

    2024年02月02日
    浏览(47)
  • Vue+Element-UI el-form表单动态检验

    业务需求: 表单el-form 有一表单项:发布时间 ,有5个选项:今天、24小时、近3天、近7天和自定义时间,其中当选择自定义时间时,后面跟着的日期时间选择器是必填的,选中其他选项时则不需要。这就需要做到表单的动态检验。 最开始实现方式是在当前表单项中设置规则

    2024年02月11日
    浏览(54)
  • vue全家桶进阶之路43:Vue3 Element Plus el-form表单组件

    在 Element Plus 中, el-form 是一个表单组件,用于创建表单以便用户填写和提交数据。它提供了许多内置的验证规则和验证方法,使表单验证更加容易。 使用 el-form 组件,您可以将表单控件组织在一起,并对表单进行验证,以确保提交的数据符合预期的格式和要求。该组件具有

    2023年04月20日
    浏览(42)
  • 在vue项目里,Element-Ui中el-form 实现一行两个表单效果

    1.首先使用elementUi中的Layout 24分栏进行布局,将整个form表单放入24分栏里 如图所示: 2.再将需要同行显示的表单放入el-row中的el-col中去 3.然后再根据你的需求控制一下表单大小就ok啦  全部代码: 效果图如下:  

    2024年02月11日
    浏览(45)
  • vue3 element-plus el-form的二次封装

    form表单的二次封装 vue3 element-plus el-form的二次封装 属性名 类型 默认值 说明 data Array [] 页面展示数据内容 onChange Function false 表单事件 bindProps Object {} 表单属性 formRef Object {} 表单ref ruleForm Object {} 数据

    2024年02月13日
    浏览(68)
  • el-form单个表单项校验方法;element-ui表单单个选项校验;el-form单个表单校验

    当我们使用element-ui的el-form时,想在提交表单前对其中一个表单进行验证时就可以使用element自带的方法“validateField” 如图: 使用示例

    2024年02月16日
    浏览(51)
  • el-form/el-form-item表单验证

    如下图所示,当触发表单验证后,输入相应的内容,表单检验通过,但是上传图片后的表单校验没有通过,需要点击表单提交触发表单提交时的校验才有效 el-form 表单,在输入内容改变元素的值后,会触发上层 el-form-item 的 el.form.chang / \\\'el.form.blur’事件,el-form-item 接收到此事

    2024年02月12日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包