Skip to content

表单组件的封装

TIP

这个表单组件只是一个封装,具体实现请自行实现。

Form.vue 组件

vue
<template>
    <el-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      label-width="100px"
      class="generic-form"
    >
      <div v-for="item in formItems" :key="item.field">
        <el-form-item :label="item.label" :prop="item.field">
          <template v-if="item.type === 'input'">
            <el-input
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
              :type="item.inputType"
            ></el-input>
          </template>
          <template v-else-if="item.type === 'select'">
            <el-select
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
            >
              <el-option
                v-for="option in item.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              ></el-option>
            </el-select>
          </template>
          <template v-else-if="item.type === 'date'">
            <el-date-picker
              v-model="formData[item.field]"
              type="date"
              :placeholder="item.placeholder"
            ></el-date-picker>
          </template>
          <template v-else-if="item.type === 'datetime'">
            <el-date-picker
              v-model="formData[item.field]"
              type="datetime"
              :placeholder="item.placeholder"
            ></el-date-picker>
          </template>
          <template v-else-if="item.type === 'radio'">
            <el-radio-group v-model="formData[item.field]">
              <el-radio
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >{{ option.label }}</el-radio>
            </el-radio-group>
          </template>
          <template v-else-if="item.type === 'checkbox'">
            <el-checkbox-group v-model="formData[item.field]">
              <el-checkbox
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >{{ option.label }}</el-checkbox>
            </el-checkbox-group>
          </template>
          <template v-else-if="item.type === 'switch'">
            <el-switch v-model="formData[item.field]"></el-switch>
          </template>
          <template v-else-if="item.type === 'password'">
            <el-input
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
              type="password"
              show-password
            ></el-input>
          </template>
          <!-- 可以根据需要添加更多表单控件类型 -->
        </el-form-item>
      </div>
      <el-form-item>
        <slot name="submit"></slot>
        <slot name="reset"></slot>
      </el-form-item>
    </el-form>
  </template>
  
  <script setup>
  import { ref, watch } from 'vue';
  
  const props = defineProps({
    modelValue: Object,
    formItems: Array,
    rules: Object,
  });
  
  const emit = defineEmits(['update:modelValue', 'submit']);
  
  const formData = ref(props.modelValue);
  const formRef = ref(null);
  
  watch(
    () => props.modelValue,
    (newValue) => {
      formData.value = newValue;
    },
    { deep: true }
  );
  
  const submitForm = () => {
    formRef.value.validate((valid) => {
      if (valid) {
        emit('submit', formData.value);
      } else {
        console.log('表单验证失败');
      }
    });
  };
  
  const resetForm = () => {
    formRef.value.resetFields();
    emit('update:modelValue', {});
  };
  </script>
  
  <style scoped lang="scss">
  .generic-form {
    width: 500px;
    margin: 20px auto;
  }
  </style>
<template>
    <el-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      label-width="100px"
      class="generic-form"
    >
      <div v-for="item in formItems" :key="item.field">
        <el-form-item :label="item.label" :prop="item.field">
          <template v-if="item.type === 'input'">
            <el-input
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
              :type="item.inputType"
            ></el-input>
          </template>
          <template v-else-if="item.type === 'select'">
            <el-select
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
            >
              <el-option
                v-for="option in item.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              ></el-option>
            </el-select>
          </template>
          <template v-else-if="item.type === 'date'">
            <el-date-picker
              v-model="formData[item.field]"
              type="date"
              :placeholder="item.placeholder"
            ></el-date-picker>
          </template>
          <template v-else-if="item.type === 'datetime'">
            <el-date-picker
              v-model="formData[item.field]"
              type="datetime"
              :placeholder="item.placeholder"
            ></el-date-picker>
          </template>
          <template v-else-if="item.type === 'radio'">
            <el-radio-group v-model="formData[item.field]">
              <el-radio
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >{{ option.label }}</el-radio>
            </el-radio-group>
          </template>
          <template v-else-if="item.type === 'checkbox'">
            <el-checkbox-group v-model="formData[item.field]">
              <el-checkbox
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >{{ option.label }}</el-checkbox>
            </el-checkbox-group>
          </template>
          <template v-else-if="item.type === 'switch'">
            <el-switch v-model="formData[item.field]"></el-switch>
          </template>
          <template v-else-if="item.type === 'password'">
            <el-input
              v-model="formData[item.field]"
              :placeholder="item.placeholder"
              type="password"
              show-password
            ></el-input>
          </template>
          <!-- 可以根据需要添加更多表单控件类型 -->
        </el-form-item>
      </div>
      <el-form-item>
        <slot name="submit"></slot>
        <slot name="reset"></slot>
      </el-form-item>
    </el-form>
  </template>
  
  <script setup>
  import { ref, watch } from 'vue';
  
  const props = defineProps({
    modelValue: Object,
    formItems: Array,
    rules: Object,
  });
  
  const emit = defineEmits(['update:modelValue', 'submit']);
  
  const formData = ref(props.modelValue);
  const formRef = ref(null);
  
  watch(
    () => props.modelValue,
    (newValue) => {
      formData.value = newValue;
    },
    { deep: true }
  );
  
  const submitForm = () => {
    formRef.value.validate((valid) => {
      if (valid) {
        emit('submit', formData.value);
      } else {
        console.log('表单验证失败');
      }
    });
  };
  
  const resetForm = () => {
    formRef.value.resetFields();
    emit('update:modelValue', {});
  };
  </script>
  
  <style scoped lang="scss">
  .generic-form {
    width: 500px;
    margin: 20px auto;
  }
  </style>

页面中调用

vue
<template>
    <div>
      <Form
        v-model="userForm"
        :form-items="formItems"
        :rules="rules"
        @submit="handleFormSubmit"
      >
        <template #submit>
          <el-button type="primary" @click="submitForm">提交</el-button>
        </template>
        <template #reset>
          <el-button @click="resetForm">重置</el-button>
        </template>
      </Form>
    </div>
  </template>
  
  <script setup>
  import { ref } from 'vue';
  import Form from '../components/Form.vue';
  
  const userForm = ref({
    name: '',
    age: '',
    gender: '',
    birthDate: '',
    password: '',
    isAgree: false,
    hobbies: [],
    startTime: '',
    endTime: '',
  });
  
  const formItems = [
    {
      label: '姓名',
      field: 'name',
      type: 'input',
      placeholder: '请输入姓名',
    },
    {
      label: '年龄',
      field: 'age',
      type: 'input',
      placeholder: '请输入年龄',
    },
    {
      label: '性别',
      field: 'gender',
      type: 'select',
      placeholder: '请选择性别',
      options: [
        { label: '男', value: 'male' },
        { label: '女', value: 'female' },
      ],
    },
    {
      label: '出生日期',
      field: 'birthDate',
      type: 'date',
      placeholder: '请选择出生日期',
    },
    {
      label: '密码',
      field: 'password',
      type: 'password',
      placeholder: '请输入密码',
    },
    {
      label: '是否同意',
      field: 'isAgree',
      type: 'switch',
    },
    {
      label: '爱好',
      field: 'hobbies',
      type: 'checkbox',
      options: [
        { label: '读书', value: 'reading' },
        { label: '运动', value: 'sports' },
        { label: '旅行', value: 'travel' },
      ],
    },
    {
      label: '开始时间',
      field: 'startTime',
      type: 'datetime',
      placeholder: '请选择开始时间',
    },
    {
      label: '结束时间',
      field: 'endTime',
      type: 'datetime',
      placeholder: '请选择结束时间',
    },
  ];
  
  const rules = {
    name: [
      { required: true, message: '请输入姓名', trigger: 'blur' },
    ],
    age: [
      { required: true, message: '请输入年龄', trigger: 'blur' },
      { pattern: /^\d+$/, message: '年龄必须为数字', trigger: 'blur' },
    ],
    gender: [
      { required: true, message: '请选择性别', trigger: 'change' },
    ],
    birthDate: [
      { required: true, message: '请选择出生日期', trigger: 'change' },
    ],
    password: [
      { required: true, message: '请输入密码', trigger: 'blur' },
      { min: 6, message: '密码长度至少为6位', trigger: 'blur' },
    ],
    startTime: [
      { required: true, message: '请选择开始时间', trigger: 'change' },
    ],
    endTime: [
      { required: true, message: '请选择结束时间', trigger: 'change' },
    ],
  };
  
  const submitForm = (formData) => {
    // 表单提交逻辑
    console.log('表单提交数据:', formData);
  };
  
  const resetForm = () => {
    // 表单重置逻辑
  };
  
  const handleFormSubmit = (formData) => {
    console.log('表单提交数据:', formData);
    // 这里可以进行表单提交的后续操作,如发送请求等
  };
  </script>
<template>
    <div>
      <Form
        v-model="userForm"
        :form-items="formItems"
        :rules="rules"
        @submit="handleFormSubmit"
      >
        <template #submit>
          <el-button type="primary" @click="submitForm">提交</el-button>
        </template>
        <template #reset>
          <el-button @click="resetForm">重置</el-button>
        </template>
      </Form>
    </div>
  </template>
  
  <script setup>
  import { ref } from 'vue';
  import Form from '../components/Form.vue';
  
  const userForm = ref({
    name: '',
    age: '',
    gender: '',
    birthDate: '',
    password: '',
    isAgree: false,
    hobbies: [],
    startTime: '',
    endTime: '',
  });
  
  const formItems = [
    {
      label: '姓名',
      field: 'name',
      type: 'input',
      placeholder: '请输入姓名',
    },
    {
      label: '年龄',
      field: 'age',
      type: 'input',
      placeholder: '请输入年龄',
    },
    {
      label: '性别',
      field: 'gender',
      type: 'select',
      placeholder: '请选择性别',
      options: [
        { label: '男', value: 'male' },
        { label: '女', value: 'female' },
      ],
    },
    {
      label: '出生日期',
      field: 'birthDate',
      type: 'date',
      placeholder: '请选择出生日期',
    },
    {
      label: '密码',
      field: 'password',
      type: 'password',
      placeholder: '请输入密码',
    },
    {
      label: '是否同意',
      field: 'isAgree',
      type: 'switch',
    },
    {
      label: '爱好',
      field: 'hobbies',
      type: 'checkbox',
      options: [
        { label: '读书', value: 'reading' },
        { label: '运动', value: 'sports' },
        { label: '旅行', value: 'travel' },
      ],
    },
    {
      label: '开始时间',
      field: 'startTime',
      type: 'datetime',
      placeholder: '请选择开始时间',
    },
    {
      label: '结束时间',
      field: 'endTime',
      type: 'datetime',
      placeholder: '请选择结束时间',
    },
  ];
  
  const rules = {
    name: [
      { required: true, message: '请输入姓名', trigger: 'blur' },
    ],
    age: [
      { required: true, message: '请输入年龄', trigger: 'blur' },
      { pattern: /^\d+$/, message: '年龄必须为数字', trigger: 'blur' },
    ],
    gender: [
      { required: true, message: '请选择性别', trigger: 'change' },
    ],
    birthDate: [
      { required: true, message: '请选择出生日期', trigger: 'change' },
    ],
    password: [
      { required: true, message: '请输入密码', trigger: 'blur' },
      { min: 6, message: '密码长度至少为6位', trigger: 'blur' },
    ],
    startTime: [
      { required: true, message: '请选择开始时间', trigger: 'change' },
    ],
    endTime: [
      { required: true, message: '请选择结束时间', trigger: 'change' },
    ],
  };
  
  const submitForm = (formData) => {
    // 表单提交逻辑
    console.log('表单提交数据:', formData);
  };
  
  const resetForm = () => {
    // 表单重置逻辑
  };
  
  const handleFormSubmit = (formData) => {
    console.log('表单提交数据:', formData);
    // 这里可以进行表单提交的后续操作,如发送请求等
  };
  </script>

程序员小洛文档