vue2-表单组件封装

文章详细描述了如何在Vue组件中使用el-form元素创建表单,包括不同类型的输入项如input、switch和select,并处理异步获取的option数据,确保数据响应式。还展示了如何在模板中使用具名插槽和事件处理。
摘要由CSDN通过智能技术生成

创建组件

components/test/index.vue

<template>
  <el-form :model="formData" :rules='rules'>
    // <!-- 具名插槽 -->
    <slot name="header" />
    <el-form-item
      v-for="(item, index) in formItem"
      :key="index"
      :label="item.label"
      :label-width="labelWith"
    >
      <template v-if="item.type === 'input'">
        <el-input v-model="formData[item.field]" />
      </template>
      <template v-else-if="item.type === 'switch'">
        <el-switch v-model="formData[item.field]" />
      </template>
      <template v-else>
        <el-select v-model="formData[item.field]" @change="(e) => issueEvent(e, item.onChange)">
          <el-option
            v-for="opt in item.option"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>
      </template>
    </el-form-item>
    // <!-- 具名插槽 -->
    <slot name="footer" />
  </el-form>
</template>

<script>
export default {
  props: {
    labelWith: {
      type: String,
      default: '100px'
    },
    formData: {
      type: Object,
      default: () => {}
    },
    formItem: {
      type: Array,
      default: () => []
    }
  },
  created() {
    console.log(this.formData, 'formData')
  },
  methods: {
    // 重点在issueEvent函数,可以给事件绑定一个空函数避免报错,如果有外部传入的自定义函数则返回这个函数
    /* 组件内函数负责分发表单项事件 */
    issueEvent(value, mouseEvent) {
      if (mouseEvent) {
        return mouseEvent(value)
      }
    }
  }
}
</script>

<style lang="scss" scoped></style>

表单项数据配置

export default {
  formItem: [
    {
      type: 'input',
      label: '颜色',
      field: 'color',
      prop: 'color',
      rule: [
			{ required: true, message: '请输入颜色', trigger: ['blur', 'change'] },
			{ validator: (rule, value, callback) => {
	          if (value !== sessionStorage.getItem('hobbies')) {
		            callback(new Error('两次输入内容不一致'))
		          } else {
		            callback()
		          }
        	  } 
            }
	    ]
    },
    {
      type: 'select',
      label: '选择大小',
      field: 'size',
      prop: 'size',
      option: [
        { label: 'S', value: '0' },
        { label: 'M', value: '1' }
      ],
      onChange: (val) => { // 传入事件
        console.log(val, 'val123')
      },
      rule: [
			{ required: true, message: '请选择大小', trigger: ['blur', 'change'] }
	  ]
    },
    {
      type: 'input',
      label: '爱好',
      field: 'hobbies',
      prop: 'hobbies',
      rule: [
			{ required: true, message: '请输入爱好', trigger: ['blur', 'change'] }
	  ]
    },
    {
      type: 'switch',
      label: '开关',
      field: 'state'
    },
    {
      type: 'select',
      label: '选择版本',
      field: 'version',
      option: [
        { label: '1.1', value: '0' },
        { label: '2.1', value: '1' }
      ]
    }
  ]
}

使用组件

注意:必须把表单项要绑定的数据变成响应式数据,使用 this.$set(object, propertyName, value)

  • object:要添加属性的目标对象。
  • propertyName:要添加的属性的名称。
  • value:要设置的属性值。
<template>
  <MyTest :form-data="formData" :form-item="formItem" :rules='rules'>
    <template #header>新增客户</template>
    <template #footer>
      <el-button type="primary" @click="submit">确定</el-button>
      <el-button>取消</el-button>
    </template>
  </MyTest>
</template>

<script>
import formConfig from '@/config/test/testConfig'
import MyTest from '@/components/test/index.vue'
export default {
  components: {
    MyTest
  },
  data() {
    return {
      formData: {}, // 表单数据
      formItem: formConfig.formItem ?? [], // ?? 表示空值合并操作符
      rules: {}
    }
  },
  watch: {
    'formData.hobbies'(newValue, oldValue) {
      console.log(newValue)
      sessionStorage.setItem('hobbies', newValue)  // 存入浏览器会话,用于自定义校验
    }
  },
  created() {
    this.formItem.forEach((item) => {
      /**
       * 使用了 Vue 实例的 $set 方法来确保 formData 对象的属性是响应式的。
       * $set 方法是 Vue 2 中用来向响应式对象添加一个属性并确保这个新属性同样是响应式的。
       */
      this.$set(this.formData, item.field, item.type === 'switch' ? false : '')
      this.$set(this.rules, item.prop, item.rule) // 动态添加表单规则
    })
  },
  methods: {
    submit() {
      console.log(this.formData, 'formData')
    }
  }
}
</script>

<style lang="scss" scoped></style>

封装 el-select

由于el-select的option数据是异步请求过来的
所以要特殊处理下

表单项数据配置

import { getDepartmentList } from '@/api/department'
// 返回一个Promise,该Promise在解析时返回一个包含formItem的对象
export default async function getFormItem() {
  const res = await getDepartmentList()
  const departmentList = res.data
  return (
    [
      {
        type: 'select',
        label: '部门',
        field: 'departmentId',
        option: departmentList.map(department => ({ // 注意:这里假设departmentList是一个数组,并且每个元素都有一个可以显示的属性(比如name)
          label: department.name, // 根据实际情况修改
          value: department.id // 根据实际情况修改
        }))
      }
    ])
}

使用组件

<template>
	<my-form :form-data="formData" :form-item="formItem" />
</ template>
<script>
	data() {
    return {
      formData: {}, // 表单数据
      // formItem: commonConfig.formItem ?? [] // ?? 表示空值合并操作符
      formItem: []
    }
  },
  async created() {
    this.formItem = await getFormItem()
    console.log(this.formItem, 'formItem')
    this.formItem.forEach((item) => {
      /**
       * 使用了 Vue 实例的 $set 方法来确保 formData 对象的属性是响应式的。
       * $set 方法是 Vue 2 中用来向响应式对象添加一个属性并确保这个新属性同样是响应式的。
       */
      this.$set(this.formData, item.field, '')
    })
  },
</ script>
`el-form-item` 和 `prop` 都是来自 Element UI 的 Vue.js 组件库,用于构建用户界面。这里,我们讨论的是如何动态地为表单字段添加 `el-form-item` 组件及其对应的属性绑定。 ### **`el-form-item` 组件简介** `el-form-item` 主要用于封装输入字段,并允许你将一些通用的功能如错误信息提示、验证规则等应用到该组件上。它通常包含以下几个关键属性: - `label`:设置输入字段的标题。 - `prop`:绑定数据到 Vue 实例的一个属性名。 - `rules`:定义表单验证规则。 - `modelValue`:绑定数据值,当值变化时触发事件。 ### **动态添加 `el-form-item`** 要在 Vue 应用中动态创建 `el-form-item` 组件并基于某个条件添加它们,你可以利用 Vue 的 `v-for` 指令。假设你有一个数组,其中包含了需要显示的表单项的信息(例如,每个元素可以包括表单标题、关联的属性名称以及是否启用的布尔值),你可以这样做: ```vue <template> <el-form ref="form"> <div v-for="(item, index) in formItems" :key="index"> <!-- 动态生成表单项 --> <el-form-item label=" {{ item.label }}" :prop="item.prop" :rules="item.rules" v-if="item.enabled"> <el-input v-model="formData[item.prop]" placeholder="请输入内容"></el-input> </el-form-item> </div> </el-form> </template> <script> export default { data() { return { formItems: [ { label: '姓名', prop: 'name', enabled: true }, { label: '邮箱', prop: 'email', enabled: false }, // 示例禁用一项 { label: '电话', prop: 'phone', enabled: true } ], formData: { name: '', email: '', phone: '' } }; }, methods: {} } </script> ``` 在这个示例中: 1. `formItems` 数组包含了我们需要动态创建的 `el-form-item` 的配置信息,包括标签文本 (`label`)、属性路径 (`prop`) 和启用状态 (`enabled`)。 2. `v-for` 指令遍历数组,根据 `enabled` 属性值来决定是否渲染每一项。 3. 使用 `:prop` 动态绑定表单字段的数据源,使用 `:rules` 动态绑定验证规则,这些都是标准的 Vue 数据绑定语法。 4. `v-model` 确保输入框的值与数据模型保持同步。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值