vue之动态表单(优化)

news2024/12/27 10:27:51

代码资源在这儿 ↑

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.coloradmin.cn/o/876955.html

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

相关文章

【数据结构】栈与队列

1 栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出 LIFO (Last In First Out) 的原则。 压栈&#xff1a;栈…

java中右移>>和无符号右移>>>的区别

public static void main(String[] args) {byte[] dest new byte[2];dest[0] 0x15; //0001 0101dest[1] (byte) 0xfb;//1111 1011System.out.println((dest[0] >> 4) & 0xff);//右移 应该是0000 0001 十进制结果显示1 结果也是1&#xff0c;正确System.out.printl…

【小练习】交互式网格自定义增删改错误记录及解决(进行中)

经过之前的学习&#xff0c;已经能创建简单的交互式网格并设置自定义增删改按钮&#xff0c;但是实现上还是存在一些问题&#xff0c;来完善优化一下。 首先是修改&#xff0c;正常修改都会弹出修改框&#xff0c;里面是之前存储的信息&#xff0c;根据实际需要对其进行修改&a…

小程序多图片组合

目录 子组件 index.js 子组件 index.wxml 子组件 index.wxss 父组件引用&#xff1a; 子组件&#xff1a;preview-image 子组件 index.js Component({properties: {previewData: {type: Array,default: [],observer: function (newVal, oldVal) {console.log(newVal, ol…

AppStream下载元数据失败

错误&#xff1a;为仓库 AppStream 下载元数据失败 : Cannot prepare internal mirrorlist: No URLs in mirrorlist 目录 一、域名解析 二、CentOS-AppStream.repo 三、CentOS-Base.repo 四、CentOS-Extras.repo 五、rpm更新 一、域名解析 先验证 ping www.baidu.com 不…

【C语言】结构体解谜:拆解数据的力量!

&#x1f341;博客主页&#xff1a;江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言—探索高效编程的基石 &#x1f4a1;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa;我的社区&#xff1a;GeekHub &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐…

9:00面试,9:06就出来了,问的问题实在有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%,…

Shell函数调用

定义一个函数&#xff0c;计算所有参数的和&#xff1a; #!/bin/bashfunction getsum(){local sum0for n in $do((sumn))donereturn $sum }getsum 10 20 55 15 #调用函数并传递参数 echo $?运行结果&#xff1a; 100

STM32 cubemx CAN

接收用到的结构体如下&#xff1a;CAN概念&#xff1a; 全称Controller Area Network&#xff0c;是一种半双工&#xff0c;异步通讯。 物理层&#xff1a; 闭环&#xff1a;允许总线最长40m&#xff0c;最高速1Mbps&#xff0c;规定总线两端各有一个120Ω电阻&#xff0c;闭环…

学习笔记整理-DOM-02-事件监听

一、什么是"事件监听" DOM允许书写JavaScript代码以让HTML元素对事件作出反应什么是"事件": 用户与网页的交互动作当用户点击元素时当鼠标移动到元素上时当文本框的内容被改变时当键盘在文本框中被按下时当网页已加载完毕时… “监听”&#xff0c;顾名思义…

项目实战 — 博客系统② {项目构建}

目录 一、创建项目 二、添加数据库 三、设置配置文件相关信息 四、 添加前端页面 五、构建项目分层 六、编写基本类 一、创建项目 二、添加数据库 -- 创建数据库 drop database if exists cat_blog; create database cat_blog DEFAULT CHARACTER SET utf8mb4;-- 使用数…

这四种订货系统不能选(一):不能独立品牌

随着商业环境的日益竞争和客户需求的不断变化&#xff0c;订货系统正逐渐成为企业管理中不可或缺的一部分。不少企业在订货系统的选择上不知从哪入手&#xff0c;今天我分享哪四种订货系统不能选。大家点个关注点个赞&#xff0c;我们接着往下看。 一、不能独立品牌的订货系统不…

C语言学习笔记---数据的存储详解

C语言程序设计笔记---015 C语言数据的存储1、数据类型的意义1.1、unsigned与signed数据类型例程11.2、补码与原码相互转换例程2 2、大小端的介绍2.1、大小端的例程12.2、大小端的例程2 --- 判断当前编译器环境属于大端或小端 3、综合练习题探究数据的存储3.1、练习题13.2、练习…

Qt 杂项(Qwt、样式等)

Qt隐藏窗口边框 this->setWindowFlags(Qt::FramelessWindowHint);Qt模态框 this->setWindowModality(Qt::ApplicationModal);QLable隐藏border 代码中设置 lable->setStyleSheet("border:0px");或者UI中直接设置样式&#xff1a;“border:0px” Qwt开源…

vue3 使用@vue-office/excel预览本地excel文件 demo

vue3 使用vue-office/excel预览excel文件 demo 显示如下&#xff1a; npm地址&#xff1a;https://www.npmjs.com/package/vue-office/excel vue-office还有pdf和docx&#xff0c;按需下载对应插件 npm install vue-office/excel vue-demivue代码如下 app.vue <templ…

2.Model、ModelMap和ModelAndView的使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

腾讯云国际站代充-阿里云ECS怎么一键迁移到腾讯云cvm?

今天主要来介绍一下如何通过阿里云国际ECS控制台一键迁移至腾讯云国际CVM。腾讯云国际站云服务器CVM提供全面广泛的服务内容。无-需-绑-定PayPal&#xff0c;代-充-值腾讯云国际站、阿里云国际站、AWS亚马逊云、GCP谷歌云&#xff0c;官方授权经销商&#xff01;靠谱&#xff0…

嵌入式Qt开发—Excel表格数据导出

有一个嵌入式Excel表格数据导出的需求&#xff1a;应用软件运行于嵌入式Linux平台上&#xff0c;在设备运行过程中&#xff0c;存储了许多数据&#xff0c;这些数据想以表格的形式导出。考虑到Windows平台的普遍性&#xff0c;需要将数据以excel表格形式导出&#xff0c;故选择…

基于机器学习的假新闻检测 -- 机器学习项目基础篇(14)

不同平台上的假新闻正在广泛传播&#xff0c;这是一个令人严重关切的问题&#xff0c;因为它导致社会稳定和人们之间建立的纽带的永久破裂。很多研究已经开始关注假新闻的分类。 在这里&#xff0c;我们将尝试在Python中的机器学习的帮助下解决这个问题。 主要步骤 导入库和数…

一生一芯4——使用星火应用商店在ubuntu下载QQ、微信、百度网盘

星火应用商店可以非常方便的完成一些应用的下载&#xff0c;下面是官方网址 http://spark-app.store/download 我使用的是intel处理器&#xff0c;无需下载依赖项&#xff0c;直接点击软件本体 我这里下载amd64,根据自己的处理器下载对应版本 sudo apt install ./spark-stor…