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;

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文简介】PP-OCRv1-v4中文字符识别论文概述

相关论文 2009.PP-OCR: A Practical Ultra Lightweight OCR System 2109.PP-OCRv2: Bag of Tricks for Ultra Lightweight OCR System 2206.PP-OCRv3: More Attempts for the Improvement of Ultra Lightweight OCR System 2308.PP-OCRv4&#xff1a;目前代码已发布&#xff08…

OKCC在系统安全方面做了哪些措施?

语音通信行业&#xff0c;运营者普遍比较关心的问题是&#xff0c;运营风险如何控制&#xff1f;运营安全如何保证&#xff1f;OKCC呼叫中心又有那些风控措施来保证运营安全。 当前阶段&#xff0c;语音通信运营&#xff0c;最主要的风险主要包括以下几个方面&#xff1a; 一、…

取证--实操

2022年美亚杯个人赛 运用软件DB Browser for SQLite &#xff08;一款用于查看SQLlite数据库文件的浏览器工具&#xff09; 火眼&#xff0c;盘古石手机取证系统等 案件详情 于2022年10月&#xff0c;有市民因接获伪冒快递公司的电邮&#xff0c;不慎地于匪徒架设的假网站提…

深入源码分析kubernetes informer机制(零)简单了解informer

[阅读指南] 基于kubernetes 1.27 stage版本 为了方便阅读&#xff0c;后续所有代码均省略了错误处理及与关注逻辑无关的部分。 文章目录 关于client-goInformer是什么为什么需要informerInformer工作流程后续分析计划 关于client-go client-go是kubernetes节点与服务端进行资源…

理解 Go 中的切片:append 操作的深入分析(篇2)

理解 Go 语言中 slice 的性质对于编程非常有益。下面&#xff0c;我将通过代码示例来解释切片在不同函数之间传递并执行 append 操作时的具体表现。 本篇为第 2 篇&#xff0c;当切片的容量 cap 不够时 func main() {// slice1 当前长度为 3&#xff0c;容量大小也为 3slice1 :…

【前端 | CSS】滚动到底部加载,滚动监听、懒加载

背景 在日常开发过程中&#xff0c;我们会遇到图片懒加载的功能&#xff0c;基本原理是&#xff0c;滚动条滚动到底部后再次获取数据进行渲染。 那怎么判断滚动条是否滚动到底部呢&#xff1f;滚动条滚动到底部触发时间的时机和方法又该怎样定义&#xff1f; 针对以上问题我…

【LNMP(分布式)】

目录 一、LNMP是什么 二、实际步骤 1.启用虚拟机 1.1 启动三台虚拟机分别命名为nginx&#xff0c;mysql&#xff0c;php 1.2 分别配置基础环境 1.3 测试外网连通性 2.更新源 3.安装nginx并配置 3.1 下载nginx源码包并安装 3.2 配置nginx 4.安装mysql并配置 4.1 安装…

Centos7 开机时遇到initramfs-xxx.img not found错误导致虚拟机无法开启问题处理

1、背景 一台运行在Esxi上面的VM重启后报initramfs-xxx.img not found错误。 按任意键后出现以下错误。 之前在运维Centos7的时候解决过Kernel panic - not syncing : VFS: Unable to mount root fs on unknown-block(0.0)错误&#xff0c;以为按照之前的解决方案&#xff0c;…

WebRTC | 实现数据流的一对一通信

目录 一、浏览器对WebRTC的支持 二、MediaStream与MediaStreamTrack 三、RTCPeerConnection 1. RTCPeerConnection与本地音视频数据绑定 2. 媒体协商SDP 3. ICE &#xff08;1&#xff09;Candidate信息 &#xff08;2&#xff09;WebRTC收集Candidate &#xff08;3&…

zabbix-6.4 监控 MySQL

目录 1、rpm安装zabbix_agentd服务 2、编写zabbix_agentd.conf文件 3、编写模板文件 4、创建mysql用户并赋权限 5、创建.my.cnf文件 6、将规则添加到SELinux策略中 注意&#xff1a; 若模板无法读取.my.cnf 信息&#xff0c;从而导致监控报错&#xff0c;可以尝试修改模…

上传excel文件

文件上传&#xff0c;其实就是用el-upload组件来实现上传&#xff0c;只是换了样式&#xff0c;和图片上传一样 <el-form-item label"选择文件"><el-input placeholder"请选择文件" v-model"form.file" disabled style"width: 45…

CCF考试:201703-1 分蛋糕(java代码)

1、【问题描述】 小明今天生日&#xff0c;他有n块蛋糕要分给朋友们吃&#xff0c;这n块蛋糕&#xff08;编号为1到n&#xff09;的重量分别为a1, a2, …, an。小明想分给每个朋友至少重量为k的蛋糕。小明的朋友们已经排好队准备领蛋糕&#xff0c;对于每个朋友&#xff0c;小明…