vue3+ts实现一个表单组件

时间:2024-07-12 07:04:50
<template> <form @submit.prevent="submitForm"> <el-form :model="formData" :rules="formRules" ref="formData" label-width="100px"> <el-form-item label="姓名" prop="name"> <el-input v-model="formData.name"></el-input> </el-form-item> <el-form-item label="手机号" prop="phone"> <el-input v-model="formData.phone"></el-input> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model.number="formData.age"></el-input> </el-form-item> <el-form-item label="学校" prop="school"> <el-input v-model="formData.school"></el-input> </el-form-item> <el-form-item label="性别" prop="gender"> <el-radio-group v-model="formData.gender"> <el-radio label="male"></el-radio> <el-radio label="female"></el-radio> </el-radio-group> </el-form-item> <el-form-item label="地点" prop="location"> <el-radio-group v-model="locationType"> <el-radio :label="'district'" @change="handleLocationTypeChange">省市区</el-radio> <el-radio :label="'street'" @change="handleLocationTypeChange">街道</el-radio> </el-radio-group> <div v-if="locationType === 'district'"> <!-- 展示省市区组件 --> <el-cascader v-model="formData.district" :options="districtOptions" @change="handleDistrictChange" placeholder="请选择省市区" ></el-cascader> </div> <div v-else-if="locationType === 'street'"> <!-- 展示街道多选组件 --> <el-select v-model="formData.street" multiple filterable remote reserve-keyword :remote-method="loadStreets" placeholder="请输入街道名称" ></el-select> </div> </el-form-item> <el-form-item> <el-button type="primary" native-type="submit">提交</el-button> </el-form-item> </el-form> </form> </template> <script setup lang="ts"> import { ref } from 'vue'; import axios from 'axios'; const formData = ref({ name: '', phone: '', age: undefined, school: '', gender: 'male', // 默认选项 district: [], // 省市区选择结果 street: [], // 街道选择结果(多选) }); const formRules = ref({ name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], phone: [ { required: true, message: '请输入手机号', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }, ], age: [ { required: true, message: '请输入年龄', trigger: 'blur' }, { type: 'number', min: 1, max: 150, message: '请输入1-150之间的数字', trigger: 'blur' }, ], school: [{ required: true, message: '请输入学校名称', trigger: 'blur' }], gender: [{ required: true, message: '请选择性别', trigger: 'change' }], district: [{ required: true, message: '请选择省市区', trigger: 'change' }], street: [{ required: true, message: '请选择街道', trigger: 'change' }], }); const locationType = ref('district'); // 默认选择省市区 const districtOptions = ref([]); // 省市区选项 // 加载街道列表 const loadStreets = async (query: string) => { try { const response = await axios.get(`/api/streets?query=${query}`); return response.data.streets.map((street: any) => ({ label: street.name, value: street.id, })); } catch (error) { console.error('Error loading streets:', error); return []; } }; // 处理地点类型变化 const handleLocationTypeChange = () => { // 清空之前选择的值 formData.street = []; }; // 处理省市区选择变化 const handleDistrictChange = () => { // 根据选择的省市区加载街道数据(这里可以根据实际需求进行调整) }; // 提交表单 const submitForm = async () => { try { await $refs.formData.validate(); if (formData.value.locationType === 'district') { // 处理省市区数据 } else if (formData.value.locationType === 'street') { // 处理街道数据 } // 提交表单逻辑,例如调用后端接口 console.log('Form data:', formData.value); // 使用 axios 发送表单数据到后端 await axios.post('/api/submit', formData.value); } catch (error) { console.error('Submit error:', error); } }; </script>