vue3基于element-plus二次封装表单组件

效果图

Form.vue

<template>
  <div>
    <el-form ref="ruleFormRef" :model="formData" :rules="rules" label-width="120px" status-icon>
      <template v-for="(item, index) in formDesc" :key="index">
        <el-form-item :label="item.label" v-if="item.type === 'select'" prop="region">
          <el-select v-model="formData.region" placeholder="please select your zone">
            <el-option
              v-for="(optionItem, optionIndex) in item.option"
              :key="optionIndex"
              :label="optionItem.label"
              :value="optionItem.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item :label="item.label" v-else-if="item.type === 'date'" prop="time">
          <el-date-picker v-model="formData.time" type="date" placeholder="Pick a date" style="width: 100%" />
        </el-form-item>
        <el-form-item :label="item.label" v-else-if="item.type === 'switch'">
          <el-switch v-model="formData.delivery" />
        </el-form-item>
        <el-form-item :label="item.label" v-else-if="item.type === 'checkbox'" prop="type">
          <el-checkbox-group v-model="formData.type">
            <el-checkbox
              v-for="(checkboxItem, checkboxIndex) in item.checkboxList"
              :key="checkboxIndex"
              :label="checkboxItem.label"
              :name="checkboxItem.name"
            />
          </el-checkbox-group>
        </el-form-item>
        <el-form-item :label="item.label" v-else-if="item.type === 'radio'" prop="resource">
          <el-radio-group v-model="formData.resource">
            <el-radio v-for="(radioItem, radioIndex) in item.radioList" :key="radioIndex" :label="radioItem.label" />
          </el-radio-group>
        </el-form-item>
        <el-form-item :label="item.label" v-else prop="name">
          <el-input v-model="formData.name" />
        </el-form-item>
      </template>
      <el-form-item>
        <el-button type="primary" @click="submitForm(ruleFormRef)">Create</el-button>
        <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script setup lang="ts">
import { rules } from './FormData'
import type { FormInstance } from 'element-plus'
interface Props {
  formDesc: any
  formData: Record<string, any>
}
const props = defineProps<Props>()
console.log(props)
const ruleFormRef = ref<FormInstance>()
interface EmitEvent {
  (e: 'submit', params: any): void
}
const emit = defineEmits<EmitEvent>()
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
      console.log(props.formData)
      emit('submit', props.formData)
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>
<style></style>

FormData.ts (表单项及校验规则)

import type { FormRules } from 'element-plus'
export const formDesc = ref([
  // 表单项
  {
    label: '标题',
    prop: 'name',
    type: 'input'
  },
  {
    label: '区域',
    prop: 'region',
    type: 'select',
    option: [
      {
        label: '上海',
        value: 'shanghai'
      },
      {
        label: '北京',
        value: 'beijing'
      }
    ]
  },
  {
    label: '选择时间',
    prop: 'time',
    type: 'date'
  },
  {
    label: '激活',
    prop: 'delivery',
    type: 'switch'
  },
  {
    label: '多选',
    prop: 'type',
    type: 'checkbox',
    checkboxList: [
      {
        label: '唱',
        name: 'APEX'
      },
      {
        label: '跳',
        name: 'APEX'
      },
      {
        label: 'RAR',
        name: 'APEX'
      },
      {
        label: '篮球',
        name: 'APEX'
      }
    ]
  },
  {
    label: '单选',
    prop: 'resource',
    type: 'radio',
    radioList: [
      {
        label: '蔡徐坤'
      },
      {
        label: '周杰伦'
      }
    ]
  }
])

export const rules = reactive<FormRules>({
  // 校验规则
  name: [
    { required: true, message: 'Please input Activity name', trigger: 'blur' },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' }
  ],
  region: [
    {
      required: true,
      message: 'Please select Activity zone',
      trigger: 'change'
    }
  ],
  time: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a date',
      trigger: 'change'
    }
  ],
  type: [
    {
      type: 'array',
      required: true,
      message: 'Please select at least one activity type',
      trigger: 'change'
    }
  ],
  resource: [
    {
      required: true,
      message: 'Please select activity resource',
      trigger: 'change'
    }
  ]
})

 父组件调用Form组件

<template>
  <el-dialog v-model="dialogVisible" title="Tips" width="50%" :before-close="cancel">
    <div>
      <Form :formData="formData" :formDesc="formDesc" @submit="handleBaseSubmit" />
    </div>
  </el-dialog>
</template>

<script lang="ts" setup>
import Form from '../commonForm/Form.vue'
import { formDesc } from '../commonForm/FormData'
const formData = reactive<Record<string, any>>({
  name: '',
  region: '',
  time: '',
  delivery: false,
  type: [],
  resource: '',
  desc: ''
})
const handleBaseSubmit = (model: Record<string, any>) => {
  console.log(model) // 获取表单数据
}
</script>
<style scoped>
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值