欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > Vue3+Vite+TypeScript+Element Plus开发-23.客制Form组件

Vue3+Vite+TypeScript+Element Plus开发-23.客制Form组件

2025/9/22 2:47:51 来源:https://blog.csdn.net/sen_shan/article/details/147385828  浏览:    关键词:Vue3+Vite+TypeScript+Element Plus开发-23.客制Form组件

 系列文档目录

Vue3+Vite+TypeScript安装

Element Plus安装与配置

主页设计与router配置

静态菜单设计

Pinia引入

Header响应式菜单缩展

Mockjs引用与Axios封装

登录设计

登录成功跳转主页

多用户动态加载菜单

Pinia持久化

动态路由 -动态增加路由

动态路由-动态删除路由 

路由守卫-无路由跳转404

 路由守卫-未登录跳转登录界面

 登录退出

Tags-组件构建

Tags-与菜单联动 

Pinia持久化优化

按钮权限

客制按钮组件

客制Table组件

客制Form组件

国际化

配置文件


文章目录

目录

 系列文档目录

文章目录

前言

子组件-Form组件构建

 父组件-Form组件调用

演示效果

​编辑

模拟测试

父组件-Form组件多界面

后续

代码下载 


前言

        在实际项目开发中,表单(Form)的数据编辑功能是常见需求。为了提高开发效率,本章节将重点介绍如何对表单组件进行封装,从而实现快速开发。


子组件-Form组件构建

创建文件:  components/ActionFormCont.vue  

实现功能:

1. 栏位定义: 控件配置由父组件传入,控件可自定义隐藏。

2. 数据来源: 控件数据由父组件提供。

3. 帅选功能: 数据选择由父组件提供。

4. 数据检证: 数据验证由父组件提供。

<template><el-formref="formRef":model="formData"label-width="120px":rules="rules"class="form"><div v-for="item in fields" :key="item.prop"><el-form-itemv-if="!item.hide":label="item.label":prop="item.prop":rules="item.rules"><el-inputv-if="item.InputType === 'text'"v-model="formData[item.prop]":disabled="item.ReadOnly":placeholder="`请输入${item.label}`"></el-input><el-selectv-else-if="item.InputType === 'select'"v-model="formData[item.prop]":disabled="item.ReadOnly"placeholder="请选择"><el-optionv-for="option in item.options":key="option.value":label="option.label":value="option.value"></el-option></el-select><el-date-pickerv-else-if="item.InputType === 'date'"v-model="formData[item.prop]":disabled="item.ReadOnly"type="date"placeholder="选择日期"@change="formatDate(item.prop, $event)"></el-date-picker></el-form-item></div></el-form></template><script lang="ts" setup>import { ref, watch, PropType, defineEmits } from "vue";import type { FormInstance } from "element-plus";interface Field {prop: string;label: string;width?: number;hide?: boolean;ReadOnly?: boolean;InputType: "text" | "select" | "date";IsNull?: boolean;Validation?: any; // 校验规则options?: { label: string; value: any }[];}const props = defineProps({fields: {type: Array as PropType<Field[]>,required: true,},data: {type: Object,default: () => ({}),},});const emit = defineEmits(["update:data"]);const formRef = ref<FormInstance | null>(null);const formData = ref({ ...props.data });watch(() => props.data, (newValue) => {formData.value = { ...newValue };}, { deep: true });watch(formData, (newValue) => {emit("update:data", newValue);}, { deep: true });const rules = props.fields.reduce((acc, field) => {acc[field.prop] = [];if (!field.IsNull) {acc[field.prop].push({required: true,message: `${field.label}不能为空`,trigger: "blur",});}if (field.Validation) {acc[field.prop].push(field.Validation);}return acc;}, {} as Record<string, any>);const formatDate = (prop: string, date: Date) => {if (date) {formData.value[prop] = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;} else {formData.value[prop] = '';}};</script><style scoped>.form {max-width: 600px;margin: 0 auto;}</style>

 父组件-Form组件调用

组件控件定义:

姓名:增加数据验证

性别:有下选框

const fields = ref([{prop: "name",label: "姓名",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: false,Validation: {validator: nameValidator,trigger: "blur",},},{prop: "age",label: "年龄",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: true,},{prop: "gender",label: "性别",width: 200,hide: false,ReadOnly: false,InputType: "select",options: [{ label: "男", value: "male" },{ label: "女", value: "female" },],IsNull: false,},{prop: "birthDate",label: "出生日期",width: 200,hide: false,ReadOnly: false,InputType: "date",IsNull: true,},
]);const handleAdd = () => {formData.value = {name: "默认姓名",};dialogVisible.value = true;
};

完整代码: 

<template><div><el-button type="primary" @click="handleAdd">新增</el-button><el-button type="success" @click="handleEdit">编辑</el-button><el-dialogv-model="dialogVisible"title="表单操作"width="50%":before-close="handleClose"><FormComponentref="formComponentRef":fields="fields"v-model:data="formData"@update:data="handleFormDataUpdate"></FormComponent><template #footer><span class="dialog-footer"><el-button @click="handleCancel">取消</el-button><el-button type="primary" @click="handleSave">保存</el-button></span></template></el-dialog></div>
</template><script lang="ts" setup>
import { ref } from "vue";
import FormComponent from "@/components/FormComponent.vue";const formComponentRef = ref(null);
const formData = ref({});
const dialogVisible = ref(false);
const nameValidator = (rule: any, value: any, callback: any) => {if (value && value.length < 3) {callback(new Error("姓名长度不能小于3"));} else {callback();}
};const fields = ref([{prop: "name",label: "姓名",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: false,Validation: {validator: nameValidator,trigger: "blur",},},{prop: "age",label: "年龄",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: true,},{prop: "gender",label: "性别",width: 200,hide: false,ReadOnly: false,InputType: "select",options: [{ label: "男", value: "male" },{ label: "女", value: "female" },],IsNull: false,},{prop: "birthDate",label: "出生日期",width: 200,hide: false,ReadOnly: false,InputType: "date",IsNull: true,},
]);const handleAdd = () => {formData.value = {name: "默认姓名",};dialogVisible.value = true;
};const handleEdit = () => {formData.value = {name: "张三",age: "25",gender: "male",birthDate: "2025-04-09",};dialogVisible.value = true;
};const handleSave = () => {(formComponentRef.value as any).$refs.formRef.validate((valid: boolean, errors: any) => {if (valid) {// 获取最新的表单数据const latestFormData = { ...formData.value };console.log("保存的数据:", latestFormData);alert("保存成功");dialogVisible.value = false;} else {// 获取具体的错误信息const errorMessages = Object.values(errors).map((error: any) => error.message).join("\n");alert(`表单校验失败:\n${errorMessages}`);}});
};const handleCancel = () => {dialogVisible.value = false;
};const handleClose = (done: () => void) => {dialogVisible.value = false;done();
};const handleFormDataUpdate = (newData: any) => {formData.value = { ...newData };
};
</script>

说明:该功能演示按钮未引用自定义组件

功能说明:
• 新增:新增时自动填充默认值,其余字段保持空白。

• 编辑:加载全部数据进行编辑。

• 保存:进行数据验证(包括长度检查和非空校验),若验证通过则保存数据。

• 取消:关闭当前窗口。

演示效果

模拟测试

保存时,获取资料正确。

验证测试已通过,此处暂不提供截图

父组件-Form组件多界面

在原有功能基础上,新增一个“新增明细”按钮,点击后可实现明细数据的新增操作。

<template><div><el-button type="primary" @click="handleAdd">新增</el-button><el-button type="success" @click="handleEdit">编辑</el-button><el-button type="info" @click="handleDetailAdd">明细新增</el-button><el-dialogv-model="dialogVisible"title="表单操作"width="50%":before-close="handleClose"><FormComponentref="formComponentRef":fields="fields"v-model:data="formData"@update:data="handleFormDataUpdate"></FormComponent><template #footer><span class="dialog-footer"><el-button @click="handleCancel">取消</el-button><el-button type="primary" @click="handleSave">保存</el-button></span></template></el-dialog><el-dialogv-model="detailDialogVisible"title="明细新增"width="50%":before-close="handleDetailClose"><FormComponentref="detailFormComponentRef":fields="detailFields"v-model:data="detailFormData"@update:data="handleDetailFormDataUpdate"></FormComponent><template #footer><span class="dialog-footer"><el-button @click="handleDetailCancel">取消</el-button><el-button type="primary" @click="handleDetailSave">保存</el-button></span></template></el-dialog></div>
</template><script lang="ts" setup>
import { ref } from "vue";
import FormComponent from "@/components/ActionFormCont.vue";const formComponentRef = ref(null);
const detailFormComponentRef = ref(null);
const formData = ref({});
const detailFormData = ref({});
const dialogVisible = ref(false);
const detailDialogVisible = ref(false);// 主表单的校验函数
const nameValidator = (rule: any, value: any, callback: any) => {if (value && value.length < 3) {callback(new Error("姓名长度不能小于3"));} else {callback();}
};// 明细表单的校验函数
const detailNameValidator = (rule: any, value: any, callback: any) => {if (value && value.length < 3) {callback(new Error("明细名称长度不能小于3"));} else {callback();}
};const fields = ref([{prop: "name",label: "姓名",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: false,Validation: {validator: nameValidator,trigger: "blur",},},{prop: "age",label: "年龄",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: true,},{prop: "gender",label: "性别",width: 200,hide: false,ReadOnly: false,InputType: "select",options: [{ label: "男", value: "male" },{ label: "女", value: "female" },],IsNull: false,},{prop: "birthDate",label: "出生日期",width: 200,hide: false,ReadOnly: false,InputType: "date",IsNull: true,},
]);const detailFields = ref([{prop: "detailName",label: "明细名称",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: false,Validation: {validator: detailNameValidator,trigger: "blur",},},{prop: "detailAmount",label: "明细金额",width: 200,hide: false,ReadOnly: false,InputType: "text",IsNull: true,},
]);const handleAdd = () => {formData.value = {name: "默认姓名",age: "",gender: "",birthDate: "",};dialogVisible.value = true;
};const handleEdit = () => {formData.value = {name: "张三",age: "25",gender: "male",birthDate: "2025-04-09",};dialogVisible.value = true;
};const handleDetailAdd = () => {detailFormData.value = {detailName: "默认明细名称",detailAmount: "100",};detailDialogVisible.value = true;
};const handleSave = () => {(formComponentRef.value as any).$refs.formRef.validate((valid: boolean, errors: any) => {if (valid) {const latestFormData = { ...formData.value };console.log("保存的数据:", latestFormData);alert("保存成功");dialogVisible.value = false;} else {const errorMessages = Object.values(errors).map((error: any) => error.message).join("\n");alert(`表单校验失败:\n${errorMessages}`);}});
};const handleDetailSave = () => {(detailFormComponentRef.value as any).$refs.formRef.validate((valid: boolean, errors: any) => {if (valid) {const latestDetailFormData = { ...detailFormData.value };console.log("明细保存的数据:", latestDetailFormData);alert("明细保存成功");detailDialogVisible.value = false;} else {const errorMessages = Object.values(errors).map((error: any) => error.message).join("\n");alert(`明细表单校验失败:\n${errorMessages}`);}});
};const handleCancel = () => {dialogVisible.value = false;
};const handleDetailCancel = () => {detailDialogVisible.value = false;
};const handleClose = (done: () => void) => {dialogVisible.value = false;done();
};const handleDetailClose = (done: () => void) => {detailDialogVisible.value = false;done();
};const handleFormDataUpdate = (newData: any) => {formData.value = { ...newData };
};const handleDetailFormDataUpdate = (newData: any) => {detailFormData.value = { ...newData };
};
</script>

多界面演示

 


后续

  下一章讲解国际化

代码下载 

GitCode - 全球开发者的开源社区,开源代码托管平台GitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode.com/sen_shan/ssVue3Demo.gitss.vue3.demo: 本项目以 Vue3、Vite、TypeScript、Element Plus 为核心框架,结合 Vue Router、Element Plus Icons、Less、Axios、Pinia、Mock 等技术,初始的构建登录,主界面,权限控制,按钮组件,table组件,form组件等小模型,可以随意搭建web管理系统https://gitee.com/sen_shan/ssVue3Demo.git

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词