前端工作室专注前端开发
 博客首页

本篇介绍表单组件的简单封装

2025-03-18 14:03:21
JS基础与深入
9
文章图片

将表单改写成通过数组形式渲染

本篇介绍表单组件的简单封装

Alt text

将表单改写成通过数组形式渲染,直接上代码

子组件

`<template>
  <el-form ref="form" :model="props.form" label-width="auto" style="max-width: 1000px">
    <el-row>
        <!--不循环row,直接循环col,放不下会自动往下换行。-->
        <el-col
          v-for="(item,index) in props.formList"
          :span="item.span || 6"
          :key="index"
        >
          <el-form-item :rules="item.rules" :label="item.label" :key="index" :prop="item.prop">
            <el-cascader v-if="item.renderType === 'ElCascader'" v-model="localForm[item.prop]" :options="item.options" />
            <component v-else :is="handleComponent(item.renderType)" v-model="localForm[item.prop]" v-bind="item">
              <template v-if="item.renderType === 'ElSelect'">
                <el-option v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-option>
              </template>
              <template v-if="item.renderType === 'ElRadioGroup'">
                <el-radio v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-radio>
              </template>
              <template v-if="item.renderType === 'ElCheckboxGroup'">
                <el-checkbox v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-checkbox>
              </template>
            </component>
          </el-form-item>
        </el-col>
      </el-row>
  </el-form>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const emit = defineEmits(['update:form']);
import { ElInputNumber, ElInput, ElSelect, ElDatePicker, ElRadioGroup, ElSwitch, ElCheckboxGroup, ElCascader } from 'element-plus';
import {type FormList, FormInter} from "@/types/types"
let props = withDefaults(defineProps<{formList?:FormList, form?:FormInter}>(),{
  formList:()=>[],
  form: ()=>({})
})
// 使用 computed 属性来创建本地响应式数据
const localForm = computed({
  get: () => props.form,
  set: (value) => {
    // 使用 $emit 向父组件发送事件来更新 form
    emit('update:form', value);
  }
});
const handleComponent = (renderType:string) => {
  switch (renderType) {
    case 'ElInput':
    return ElInput
    case 'ElInputNumber':
    return ElInputNumber
    case 'ElSelect':
    return ElSelect
    case 'ElDatePicker':
    return ElDatePicker
    case 'ElRadioGroup':
    return ElRadioGroup
    case 'ElSwitch':
    return ElSwitch
    case 'ElCheckboxGroup':
    return ElCheckboxGroup
    case 'ElCascader':
    return ElCascader
    default:
      return renderType
  }
}
</script>`

父组件

<template>
  <div>
    表单组件封装
    <div>数据:{{ form }}</div>
    <lee-form :form="form" :formList="formList" @update:form="updateForm" />
  </div>
</template>
<script setup lang="ts">
import { reactive,computed } from 'vue'
import { type FormList, FormInter } from '@/types/types'
import LeeForm from '@/components/form/leeForm.vue'
const formList = computed<FormList[]>(()=>[
  {
    renderType: 'ElInput',
    label: '姓名',
    prop: 'name',
    rules: [
      { required: true, message: '请输入姓名', trigger: 'blur' }
    ]
  },
  {
    renderType: 'ElInputNumber',
    label: '年龄',
    prop: 'age',
    rules: [ // 动态校验
      { required:form.name, message: '请输入姓名', trigger: 'blur' }
    ]
  },
  {
    renderType: 'ElSelect',
    label: '性别',
    prop: 'sex',
    options: [
      { label: '男', value: '男' },
      { label: '女', value: '女' }
    ]
  },
  {
    renderType: 'ElDatePicker',
    label: '生日',
    prop: 'birthday'
  },
  {
    renderType: 'ElRadioGroup',
    label: '婚姻状况',
    prop: 'marriage',
    options: [
      { label: '未婚', value: '未婚' },
      { label: '已婚', value: '已婚' }
    ]
  },
  {
    renderType: 'ElSwitch',
    label: '开关',
    prop: 'switch'
  },
  {
    renderType: 'ElCheckboxGroup',
    label: '多选框',
    prop: 'checkboxGroup',
    options: [
      { label: '1', value: '1' },
      { label: '2', value: '2' }
    ]
  },
  {
    renderType: 'ElCascader',
    label: '级联选择器',
    prop: 'elCascader',
    options: [
      {
        value: 'guide',
        label: 'Guide',
        children: [
          {
            value: 'disciplines',
            label: 'Disciplines',
            children: [
              {
                value: 'consistency',
                label: 'Consistency'
              }
            ]
          }
        ]
      }
    ]
  },
  {
    renderType: 'ElInput',
    label: '备注',
    prop: 'note',
    rows: 2,
    type: 'textarea'
  },
])
const form = reactive<FormInter>({
  name: '',
  elCascader:[]
})
/**
 * 更新表单数据
 * @param {Record<string, any>} val - 需要更新的表单数据对象
 * @description 通过 Object.assign 方法将传入的数据对象合并到现有表单对象中
 */
const updateForm = (val: Record<string, any>) => {
  console.log(val)
  Object.assign(form, val)
}
</script>
<style scoped></style>

githuab地址为:'https://github.com/leezhenwang/vue3-TypeScript-demo.git/

小恐龙

专注于WEB和移动前端开发

5年以上经验业余讲师被访问基金爱好者
社交帐号