vue3+ts实现一个表单组件
<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>