vue3 + antd 封装动态表单组件(一)

news2024/11/27 18:28:01

前置条件:

vue版本 v3.3.11
ant-design-vue版本 v4.1.1

创建动态组件配置文件config.js

import { Input, Textarea, InputNumber, Select, RadioGroup, CheckboxGroup, DatePicker } from 'ant-design-vue';

// 表单域组件类型
export const componentsMap = {
    Text: Input,
    Textarea,
    Number: InputNumber,
    Select,
    Radio: RadioGroup,
    Checkbox: CheckboxGroup,
    DatePicker,
}

创建dynamic-form.vue组件

<template>
  <div>
    <a-form ref="formRef" :model="formModel">
      <a-form-item
        :name="item.field"
        :label="item.label"
        v-for="item in formSchema"
        :key="item.field"
        v-bind="item.formItemProps"
      >
        <component
          :is="componentsMap[item.component]"
          v-bind="item.componentProps"
          v-model:value="formModel[item.field]"
        />
      </a-form-item>
    </a-form>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from "vue";
import { componentsMap } from "./config.js";

const props = defineProps({
  // 表单项配置
  schema: {
    type: Array,
    default: () => [],
  },
  // 表单model配置,一般用于默认值、回显数据
  model: {
    type: Object,
    default: () => ({}),
  },
});

const formRef = ref(null);

const formSchema = ref([]);
const formModel = ref({});

// 表单初始化
const initForm = () => {
  formSchema.value = props.schema.map((x) => {
    return {
      ...x,
    };
  });

  // model初始数据
  formModel.value = props.schema.reduce((pre, cur) => {
    if (!pre[cur.field]) {
      // 表单初始数据(默认值)
      pre[cur.field] = cur.value;
      return pre;
    }
  }, {});
};

onMounted(() => {
  initForm();
  // 构建表单项后才回显model值,model会覆盖schema配置的value值
  watch(
    () => props.model,
    (newVal) => {
      formModel.value = { ...formModel.value, ...newVal };
    },
    {
      immediate: true,
      deep: true,
    }
  );
});

// 表单验证
const validateFields = () => {
  return new Promise((resolve, reject) => {
    formRef.value
      .validateFields()
      .then((formData) => {
        resolve(formData);
      })
      .catch((err) => reject(err));
  });
};

// 表单重置
const resetFields = (isInit = true) => {
  // 是否清空默认值
  if (isInit) {
    formModel.value = {};
  }
  formRef.value.resetFields();
};

// 暴露方法
defineExpose({
  validateFields,
  resetFields,
});
</script>

使用dynamic-form.vue组件

<template>
  <div style="padding: 200px">
    <DynamicForm ref="formRef" :schema="schema" :model="model" />
    <div style="display: flex; justify-content: center">
      <a-button @click="handleReset(true)">重置(全部清空)</a-button>
      <a-button style="margin-left: 50px" @click="handleReset(false)"
        >重置</a-button
      >
      <a-button type="primary" style="margin-left: 50px" @click="handleSubmit"
        >提交</a-button
      >
    </div>
  </div>
</template>

<script setup>
import DynamicForm from "@/components/form/dynamic-form.vue";
import { ref } from "vue";
import dayjs from "dayjs";
const formRef = ref(null);

const schema = ref([
  {
    label: "姓名",
    field: "name",
    component: "Text",
    componentProps: {
      allowClear: true,
      showCount: true,
      maxlength: 20,
      style: {
        width: "500px",
      },
    },
    formItemProps: {
      rules: [
        {
          required: true,
          message: "请输入姓名",
          trigger: "blur",
        },
      ],
    },
  },
  {
    label: "性别",
    field: "sex",
    component: "Radio",
    componentProps: {
      options: [
        { value: 1, label: "男" },
        { value: 2, label: "女" },
        { value: 3, label: "保密" },
      ],
    },
    formItemProps: {
      rules: [
        {
          required: true,
          message: "请选择性别",
          trigger: "blur",
        },
      ],
    },
    value: 1,
  },
  {
    label: "生日",
    field: "birthday",
    component: "DatePicker",
    formItemProps: {
      rules: [
        {
          required: true,
          message: "生日日期不能为空",
          trigger: "blur",
        },
      ],
    },
  },
  {
    label: "兴趣",
    field: "hobby",
    component: "Checkbox",
    componentProps: {
      options: [
        { value: 1, label: "足球" },
        { value: 2, label: "篮球" },
        { value: 3, label: "排球" },
      ],
    },
  },
  {
    label: "国家",
    field: "country",
    component: "Select",
    componentProps: {
      allowClear: true,
      options: [
        { value: 1, label: "中国" },
        { value: 2, label: "美国" },
        { value: 3, label: "俄罗斯" },
      ],
    },
  },
  {
    label: "简介",
    field: "desc",
    component: "Textarea",
    componentProps: {
      allowClear: true,
      autoSize: {
        minRows: 4,
        maxRows: 4,
      },
      maxlength: 200,
      showCount: true,
    },
  },
]);
const model = ref({ name: "百里守约" });
// 提交
const handleSubmit = async () => {
  const formData = await formRef.value.validateFields();
  if (formData.birthday) {
    formData.birthday = dayjs(formData.birthday).format("YYYY-MM-DD");
  }
  console.log("提交信息:", formData);
};

// 重置
const handleReset = (isInit) => {
  formRef.value.resetFields(isInit);
};
</script>

效果图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编译poco库出现的问题及其解决办法

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 使用vs2015编译poco库出现问题&#xff1a;error C3688: invalid literal suffix ‘I64_FMT’; literal operator or literal operator template ‘opera…

大模型:我也会自监督学习~

前言 当下大模型的能力已经很强了&#xff0c;但是将来我们想要的是能力更强的大模型&#xff0c;其最好能够处理各种复杂问题也即强对齐模型。 之前大模型训练的监督信号主要来源于人类反馈&#xff0c;但是如果想要训练一个强对齐模型必然就需要一个对应的强监督信号&#…

第二篇【传奇开心果系列】Vant 开发移动应用:开发常见页面

传奇开心果博文系列 Vant of Vue 开发移动应用示例系列博文博文目录一、常见页面的重要作用二、常见页面介绍三、分别示例代码四、常见页面样式示例代码五、主要知识点总结 Vant of Vue 开发移动应用示例系列博文 博文目录 一、常见页面的重要作用 常见页面在移动应用中扮演…

手把手教你如何快速定位bug,如何编写测试用例,快来观摩......

手把手教你如何快速定位bug,如何编写测试用例,快来观摩......手把手教你如何快速定位bug,如何编写测试用例,快来观摩......作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xf…

算法第二十一天-丑数

丑数 题目要求 解题思路 首先判断数字是不是为0或者负数&#xff0c;两者均不可能成为丑数&#xff1b; 之后对n进行不断整除&#xff0c;直到无法除尽为止。 简单判断最后的数是不是1即可。 代码 class Solution:def isUgly(self, n: int) -> bool:if n<0:return Fa…

linux perf工具使用

参考文章Linux性能调优之perf使用方法_perf交叉编译-CSDN博客 perf是一款Linux性能分析工具。比如打流性能优化的时候&#xff0c;就能够看到是哪些函数消耗的cpu高 那么linux如何编译perf工具呢&#xff1f; perf工具编译 进入perf目录下linux-3.16/tools/perf make ARCH…

线程状态转换

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程⛺️稳中求进&#xff0c;晒太阳 程状态转换 假设有线程Thread t 情况1 new-->RUNNABLE 当调用t.start()方法时&#xff0c;由new ->RUNNABLE 情况2 RUNNABLE WAITING t…

Spark On Hive配置测试及分布式SQL ThriftServer配置

文章目录 Spark On Hive的原理及配置配置步骤在代码中集成Spark On Hive Spark分布式SQL执行原理及配置配置步骤在代码中集成Spark JDBC ThriftServer 总结 Spark On Hive的原理及配置 Spark本身是一个执行引擎&#xff0c;而没有管理metadate的能力&#xff0c;当我们在执行S…

Redis原理篇(SkipList)

一.概述 本质是双端链表&#xff0c;只不过在正向遍历时可以不一个一个遍历&#xff0c;而是可以跳着遍历。 怎么实现的呢&#xff0c;下面是SkipList源码 二.源码 1. zskiplist 意义&#xff1a;跳表 zskiplist里面有头指针和尾指针&#xff0c;节点数量&#xff0c;最大…

Python自动化测试【selenium面试题】

一、selenium中如何判断元素是否存在&#xff1f; expected_conditions模块提供了16种判断方法&#xff0c;以下方法是判断元素存在DOM中&#xff1a; presence_of_element_located """ An expectation for checking that an element is present on the DOM of…

第二百七十八回

文章目录 1. 概念介绍2. 使用方法2.1 DropdownMenu2.1 DropdownMenuEntry 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何禁止页面跟随手机自动旋转"相关的内容&#xff0c;本章回中将介绍DropdownMenu组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1.…

免费的网站站群软件,批量管理不同网站程序

在网站运营的过程中&#xff0c;站群软件成为提高效率、管理多个网站的得力助手。本文将专心分享三款卓越的站群软件&#xff0c;其中特别推荐147SEO软件&#xff0c;它不仅能够批量管理网站&#xff0c;还能自动更新原创文章&#xff0c;并主动推送各大搜索引擎。不论您运营何…

logstack 日志技术栈-02-ELK 的缺点?loki 更轻量的解决方案?

ELK/EFK日志系统 如果今天谈论到要部署一套日志系统&#xff0c;相信用户首先会想到的就是经典的ELK架构&#xff0c;或者现在被称为Elastic Stack。 Elastic Stack架构为Elasticsearch Logstash Kibana Beats的组合&#xff0c;其中&#xff0c;Beats负责日志的采集&…

51单片机中断

1、什么是中断&#xff1f; CPU在处理某一事件A时&#xff0c;发生了另一事件B请求CPU迅速去处理&#xff08;中断发生&#xff09;&#xff1b; CPU暂时中断当前的工作&#xff0c;转去处理事件B&#xff08;中断响应和中断服务&#xff09;&#xff1b; 待CPU将事件B处理完…

解决一个mysql的更新属性长度问题

需求背景&#xff1a; 线上有一个 platform属性&#xff0c;原有长度为 varchar(10)&#xff0c;但是突然需要填入一个11位长度的值&#xff1b;而偏偏这个属性在线上100张表中有50张都存在&#xff0c;并且名字各式各样&#xff0c;庆幸都包含 platform&#xff1b;例如 platf…

【计算机网络】Socket的TCP_NODELAY选项与Nagle算法

TCP_NODELAY是一个套接字选项&#xff0c;用于控制TCP套接字的延迟行为。当TCP_NODELAY选项被启用时&#xff0c;即设置为true&#xff0c;就会禁用Nagle算法&#xff0c;从而实现TCP套接字的无延迟传输。这意味着每次发送数据时都会立即发送&#xff0c;不会等待缓冲区的填充或…

PostgreSQL命令大全

文章目录 连接与退出数据库操作表操作外键约束视图操作存储过程与函数权限管理事务管理查询优化与分析数据类型转换分区表操作复制与备份恢复 PostgreSQL是一个功能强大的开源关系型数据库管理系统&#xff0c;以下是一些基本且常用的命令按功能分类&#xff1a; 连接与退出 连…

【内存管理】flink内存管理(一):内存管理概述:flink主动管理内存原理、flink内存模型

文章目录 一.flink为什么自己管理内存1. 处理大数据时JVM内存管理的问题2. flink主动管理内存逻辑2.1. Flink内存管理方面2.2. 序列化、反序列化说明 3. Flink主动管理内存的好处 二. Flink内存模型1. 堆内存2. 非堆内存2.1. 托管内存2.2.直接内存2.3. JVM特定内存 本节从整体使…

【每日一题】2788. 按分隔符拆分字符串-2024.1.20

题目&#xff1a; 2788. 按分隔符拆分字符串 给你一个字符串数组 words 和一个字符 separator &#xff0c;请你按 separator 拆分 words 中的每个字符串。 返回一个由拆分后的新字符串组成的字符串数组&#xff0c;不包括空字符串 。 注意 separator 用于决定拆分发生的位…

循序渐进学 JavaScript <一>

这周复习完了 js 基础&#xff0c;整理一波~ 一、认识 JavaScript 1. 1 编程语言 计算机语言&#xff1a;概念比较广泛&#xff0c;包括 html 标记语言&#xff08;它并不是编程语言&#xff09;编程语言特点 具有数据和数据结构指令和流程控制&#xff1a;switch&#xff0c…