vue之动态表单(优化)
代码资源在这儿 ↑
vue之动态表单优化
- vue2+js动态表单优化
- vue3+ts动态表单优化
vue2+js动态表单优化
效果图

目录结构

五个文件的完整代码:
以下是App.vue
<template><div><router-view></router-view><Formpage /></div>
</template><script>
import Formpage from './views/FormPage.vue';export default {components: {Formpage},
}
</script>
以下是FormPage.vue
<template><div class="container"><FormItemComp :formState="root"></FormItemComp></div>
</template><script>
import FormItemComp from '../components/FormItemComp.vue';
import root from './FormPageDatas';export default {components: {FormItemComp},data() {return {root: root}}
}
</script><style scoped>
.container {width: 80%;margin: 1em auto;
}
</style>
以下是FormItemComp.vue
<template><el-form><template v-if="formState"><el-form-item :label="formState.payload.label"><template v-if="formState.type === 'input'"><el-input v-model="formState.payload.value"/></template><template v-else-if="formState.type === 'checkbox'"><el-checkbox-group v-model="formState.payload.value"><el-checkbox v-for="option in formState.payload.options" :key="option.value" :label="option.value">{{ option.label }}</el-checkbox></el-checkbox-group></template><template v-else-if="formState.type === 'radio'"><el-radio-group v-model="formState.payload.value"><el-radio v-for="option in formState.payload.options" :key="option.value" :label="option.value">{{ option.label }}</el-radio></el-radio-group></template><template v-else-if="formState.type === 'select'"><el-select v-model="formState.payload.value"><el-option v-for="option in formState.payload.options" :key="option.value" :label="option.label" :value="option.value"/></el-select></template></el-form-item><FormItemComp :form-state="getNext()"/></template></el-form>
</template><script>
export default {name: 'FormItemComp',props: {formState: {type: Object,default: null}},methods: {getNext() {let current = this.formState;if (!current) {return null;}const ancestors = [];ancestors.unshift(current);while ((current = current.parent)) {ancestors.unshift(current);}return this.formState.next(this.formState, ancestors);}}
}
</script><style scoped>
.el-form-item__label {padding-right: 10px !important;
}
</style>
以下是FormItem.js
import Vue from 'vue';/*** 创建表单项* @param formItemType string 表单项的类型* @param payload object 表单项的label、options、value* @param next function 当前选择的值* @param parent 上一个表当项* @return {{next: ((function(*=, *=): (null|null))|*), parent: null, payload, type}}*/
export function createFormItem(formItemType, payload, next, parent) {if (!next) {next = () => null;}if (!parent) {parent = null;}const nextFunc = function(current, acients) {let nextItem = next(current, acients);if (!nextItem) {return null;}nextItem.parent = current;if (!Vue.observable(nextItem)) {nextItem = Vue.observable(nextItem);}return nextItem;};return Vue.observable({type: formItemType,payload: payload,next: nextFunc,parent: parent,});
}
以下是FormPageDatas.js
import {createFormItem} from '@/FormItem';const item1 = createFormItem('select',{label: 'test1',options: [{label: 'test1-1', value: 'test1-1'},{label: 'test1-2', value: 'test1-2'},{label: 'test1-3', value: 'test1-3'},],value: 'test1-1',},(current) => {if (current.payload.value === 'test1-2') {return item2;} else if (current.payload.value === 'test1-3') {return item4;} else {return null;}}
);const item2 = createFormItem('input', {label: 'test2',value: 'test'
}, (current) => (current.payload.value === 'test2' ? item3 : null));const item3 = createFormItem('checkbox',{label: 'test3',options: [{label: 'test3-1', value: 'test3-1'},{label: 'test3-2', value: 'test3-2'},{label: 'test3-3', value: 'test3-3'},],value: ['test3-2', 'test3-3'],},(current) => (current.payload.value.includes('test3-1') ? item4 : null)
);const item4 = createFormItem('radio', {label: 'test4',options: [{label: 'test4-1', value: 'test4-1'},{label: 'test4-2', value: 'test4-2'},{label: 'test4-3', value: 'test4-3'},{label: 'test4-4', value: 'test4-4'},],value: 'test4-4',
});export default item1;
vue3+ts动态表单优化
效果图

目录结构

五个文件的完整代码:
以下是App.vue
<template><div><Formpage /></div>
</template><script setup lang="ts">
import Formpage from './views/Formpage.vue';
</script>
以下是FormPage.vue
<template><div class="container"><FormItemComp :form-state="root"></FormItemComp></div>
</template><script setup lang="ts">
import FormItemComp from '../components/FormItemComp.vue';
import root from './FormPageDatas';
</script><style scoped>
.container {width: 80%;margin: 1em auto;
}
</style>
以下是FormItemComp.vue
<template><template v-if="formState"><a-form-item :label="formState.payload.label"><template v-if="formState.type === 'input'"><a-input v-model:value="formState.payload.value" /></template><template v-else-if="formState.type === 'checkbox'"><a-checkbox-group v-model:value="formState.payload.value"><a-checkbox v-for="option in formState.payload.options" :value="option.value">{{ option.label }}</a-checkbox></a-checkbox-group></template><template v-else-if="formState.type === 'radio'"><a-radio-group v-model:value="formState.payload.value"><a-radio v-for="option in formState.payload.options" :value="option.value">{{ option.label }}</a-radio></a-radio-group></template><template v-else-if="formState.type === 'select'"><a-select v-model:value="formState.payload.value"><a-select-option v-for="option in formState.payload.options" :value="option.value">{{ option.label }}</a-select-option></a-select></template></a-form-item><FormItemComp :form-state="getNext()"></FormItemComp></template>
</template><script setup lang="ts">
import { FormItem } from '../FormItem';const props = defineProps<{formState: FormItem | null;
}>();function getNext(): FormItem | null {let current: FormItem | null = props.formState;if (!current) {return null;}const acients = [];acients.unshift(current);while ((current = current.parent)) {acients.unshift(current);}return props.formState!.next(props.formState!, acients);
}
</script><style>
.ant-form-item-label {padding-right: 10px !important;
}
</style>
以下是FormItem.ts
import { isReactive, reactive } from 'vue';export type FormItemType = 'input' | 'select' | 'checkbox' | 'radio';export interface FormItem {type: FormItemType;payload: any;next: (current: FormItem, acients: FormItem[]) => FormItem | null;parent: FormItem | null;
}export function createFormItem(formItemType: FormItem['type'],payload: FormItem['payload'],next?: FormItem['next'],parent?: FormItem['parent']
): FormItem {if (!next) {next = () => null;}if (!parent) {parent = null;}const nextFunc: FormItem['next'] = (current, acients) => {let nextItem = next!(current, acients);if (!nextItem) {return null;}nextItem.parent = current;if (!isReactive(nextItem)) {nextItem = reactive(nextItem);}return nextItem;};const formItem: FormItem = reactive({type: formItemType,payload,next: nextFunc,parent,});return formItem;
}
以下是FormPageDatas.ts
import { createFormItem } from '../FormItem';const item1 = createFormItem('select',{label: 'test1',options: [{ label: 'test1-1', value: 'test1-1' },{ label: 'test1-2', value: 'test1-2' },{ label: 'test1-3', value: 'test1-3' },],value: 'test1-1',},(current) => {if (current.payload.value === 'test1-2') {return item2;} else if (current.payload.value === 'test1-3') {return item4;} else {return null;}}
);const item2 = createFormItem('input',{ label: 'test2', value: 'test' },(current) => (current.payload.value === 'test2' ? item3 : null)
);const item3 = createFormItem('checkbox',{label: 'test3',options: [{ label: 'test3-1', value: 'test3-1' },{ label: 'test3-2', value: 'test3-2' },{ label: 'test3-3', value: 'test3-3' },],value: ['test3-2', 'test3-3'],},(current) => (current.payload.value.includes('test3-1') ? item4 : null)
);const item4 = createFormItem('radio', {label: 'test4',options: [{ label: 'test4-1', value: 'test4-1' },{ label: 'test4-2', value: 'test4-2' },{ label: 'test4-3', value: 'test4-3' },{ label: 'test4-4', value: 'test4-4' },],value: 'test4-4',
});export default item1;相关文章:
vue之动态表单(优化)
代码资源在这儿 ↑ vue之动态表单优化 vue2js动态表单优化vue3ts动态表单优化 vue2js动态表单优化 效果图 目录结构 五个文件的完整代码: 以下是App.vue <template><div><router-view></router-view><Formpage /></div> </templa…...
web连接桌面打开gptmap
一:环境配置 需要的材料: python-3.10.4 我使用的是这个版本的,3.8.10 该版本和以下版本组件组合,验证过能正常运行(python 3.6.8测试异常) websockify 该项目有python版本和node js版本 noVNC 形式的app…...
做好需求分析的4大关键认知
探索如何正确的需求分析?本文详细介绍了4大关键点,帮助您明确用户与产品需求、深入挖掘用户动机,并为产品经理提供筛选需求的实用建议。 一、什么是需求分析以及重要性 需求分析指的是在建立一个新的或改变一个现存的产品时,确定新…...
Max Compute 操作记录
编译 max compute-spark git clone https://github.com/aliyun/MaxCompute-Spark cd spark-3.x mvn clean package -DskipTests在 target 目录下生成 以下两个文件。 spark-examples_2.12-1.0.0-SNAPSHOT-shaded.jar spark-examples_2.12-1.0.0-SNAPSHOT.jar2. DataWorks 上传…...
Windows 11 + Ubuntu20.04 双系统 坑里爬起来
ThinkPad x390 安装双系统,原有的磁盘太小,扩充了磁盘重新装系统,出现的问题,加以记录。 1. windows和ubuntu谁先安装,两个都可以,一般建议先安装windows,后安装ubuntu 2. 安装windows后&…...
touch手势事件及功能封装
文章目录 基本概念事件类型事件对象的属性touch事件封装单击,双击滑动方向(上下左右)距离角度 缩放旋转 常用功能封装滑动图片浏览实现拖拽操作游戏角色移动、跳跃 封装手写板功能 在现代Web开发中,移动设备的普及使得触摸屏交互成…...
面试问题记录
1.多线程,线程池 1.如何创建线程 实现 Runnable 接口,重写run方法;实现 Callable 接口,重写call方法;继承 Thread 类,重写run方法。 2.基础线程机制 Executors:可以创建四种类型的线程池&am…...
ZooKeeper的应用场景(集群管理、Master选举)
5 集群管理 随着分布式系统规模的日益扩大,集群中的机器规模也随之变大,因此,如何更好地进行集群管理也显得越来越重要了。 所谓集群管理,包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后…...
面试算法编程题
面试算法编程题记录 题目 : 羊圈里的狼 题目背景 : 一到了晚上,草原牧民的羊就会被赶进羊圈里。这时,野外的狼群就会打羊羔的主意。为了保护羊羔,牧民需要将羊圈里的狼赶走或杀死。由于来的狼很多,他需要快速甄别哪些狼在羊圈里面…...
JVM——JDK 监控和故障处理工具总结
文章目录 JDK 命令行工具jps:查看所有 Java 进程jstat: 监视虚拟机各种运行状态信息 jinfo: 实时地查看和调整虚拟机各项参数jmap:生成堆转储快照**jhat**: 分析 heapdump 文件**jstack** :生成虚拟机当前时刻的线程快照 JDK 可视化分析工具JConsole:Java 监视与管理控制台连接…...
多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测
多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经网络的数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现WOA-CNN鲸鱼算法优化卷积神经…...
ZoomIt v7.1
ZoomIt 是用于技术展示和演示的屏幕缩放、注释和录制工具。 还可以使用 ZoomIt 将屏幕截图截取到剪贴板或文件。 ZoomIt 在系统托盘中不显眼地运行,可使用可自定义的热键激活,它能够放大屏幕区域,在缩放时四处移动,并在缩放后的图…...
E8—Aurora 64/66B ip实现GTX与GTY的40G通信2023-08-12
1. 场景 要在贴有K7系列FPGA芯片的板子和贴有KU系列FPGA芯片的板子之间通过光模块光纤QSFP实现40G的高速通信。可以选择的方式有多种,但本质的方案就一种,即实现4路GTX与GTY之间的通信。可以选择8B/10B编码通过GT IP核实现,而不能通过Aurora…...
js下载后端返回的文件
文件流下载 后端返回文件流形式,前端下载 // res 为请求返回的数据对象const file_data res.data // 后端返回的文件流const blob new Blob([file_data]) const href window.URL.createObjectURL(blob) // 创建下载的链接 const file_name decodeURI(res.header…...
计组 | 并行操作
前言 记录一些计组相关联的题集与知识点,方便记忆与理解。 并行 什么是并行处理 广义地讲,并行性有两种含义:一是同时性,指两个或多个事件在同一时刻发生;二是并发性,指两个或多个事件在同一时间间隔内发生…...
rabbitmq容器启动后修改连接密码
1、进入容器 docker exec -it rabbitmq bash 2、查看当前用户列表 rabbitmqctl list_users 3、修改密码 rabbitmqctl change_password [username] ‘[NewPassword]’ 4、修改后退出容器 ctrlpq 5、退出容器后即可生效,不需要重启容器...
PHP中的curl详细解析和常见大坑
这篇文章主要介绍了 PHP 中使用 CURL 之 php curl 详细解析和常见大坑 ,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧。好啦,长话短说再长说,祭出今天的工具——CURL(Client URL Library),当然今天以 PHP…...
[python] 使用Jieba工具中文分词及文本聚类概念
前面讲述了很多关于Python爬取本体Ontology、消息盒InfoBox、虎扑图片等例子,同时讲述了VSM向量空间模型的应用。但是由于InfoBox没有前后文和语义概念,所以效果不是很好,这篇文章主要是爬取百度5A景区摘要信息,再利用Jieba分词工…...
常见程序搜索关键字转码
个别搜索类的网站因为用户恶意搜索出现误拦截情况,这类网站本身没有非法信息,只是因为把搜索关键字显示在网页中(如下图),可以参考下面方法对输出的关键字进行转码 DEDECMS程序 本文针对Dedecms程序进行搜索转码&…...
细谈商品详情API接口设计
一、引言 随着互联网技术的发展,商品详情信息的展示和交互变得越来越重要。为了提供更好的用户体验,我们需要设计一套高效、稳定且易于扩展的商品详情API接口。本文将详细探讨商品详情API接口的设计,包括接口的通用性、安全性和扩展性等方面…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
