格子表单GRID-FORM | 嵌套子表单与自定义脚本交互

格子表单/GRID-FORM已在Github 开源,如能帮到您麻烦给个星🤝

GRID-FORM 系列文章

  • 基于 VUE3 可视化低代码表单设计器
  • 嵌套表单与自定义脚本交互

新版本功能 🎉

不觉间,GRID-FORM 已经开源一年(2023年1月29日首次提交),初始版本功能较为简单,能用但很死板。后来陆续进行小版本迭代,增加诸如数据联动右键菜单等,可是作为常用且必要的嵌套(子表单)按钮功能一直没有实现。于是就有了今年的第一个0.1.1版本:

  • 支持嵌套容器(子表单)
  • 支持自定义脚本交互
  • 新增 Element Plus 渲染器,完善 Vant4 渲染器
  • 新增组件:按钮、图片、静态表格

目前具备的模块与组件如下图(带边框为新增功能)所示:

运行时截图

表单渲染效果

从左到右分别是 NaiveUI、ElementPlus、Vant4对于同一表单的渲染效果

可视化设计器

子表单(嵌套)

所谓子表单,可以理解为大背包里面的小包,底下可以添加子字段,同时支持录入多条数据;常见应用于录入字段格式固定、条数不定的数据清单。

按照 GRID-FORM 的设计,初始表单为一个顶层容器,能够定义标签样式(如位置、对齐方式)、格子列数、尺寸大小等布局属性,还可以嵌套子容器(如上图中的外层容器子容器1子容器2),每个容器均能定义其布局属性,理论上支持无限嵌套(递归渲染)。
渲染流程

嵌套类型

子表单能够设置如下类型:

类型说明
仅布局只作为布局上的分组,字段均为同级
单个嵌入一个对象到父字段
多行嵌入多个格式固定的对象(数组)到父字段

下面我用一个实际例子说明,比如要录入一则学生信息,字段包含:

字段名说明
姓名、年龄、籍贯仅布局三个同级基本信息
专业信息单个数据:名称、学院、学年
教育经历多行数据:开始日期、结束日期、学校

最终得到的表单数据:

{姓名 : "张三",年龄 : 19,籍贯 : "广西",专业 : {名称 : "水利水电工程",学院 : "土木建筑工程学院",学年 : 4},教育经历 : [{ 开始日期 : "2011.09",结束日期 : "2020.06",学校 : "XX市第一小学"},{ 开始日期 : "2020.09",结束日期 : "2023.06",学校 : "XX市第一高级中学"}]
}

效果演示

核心代码

<template><template v-if="isMultiple"><table class="gf-render-table"><tr v-for="(rowData, rowIndex) in formData" :class="{striped:rowIndex%2==1}"><td width="40" class="c"><n-popconfirm :negative-text="null" @positive-click="formData.splice(rowIndex, 1)"><template #trigger><n-button size="small" type="primary" tertiary circle>{{rowIndex+1}}</n-button></template>删除第{{rowIndex+1}}行数据?</n-popconfirm></td><td><n-grid :x-gap="gridGap" :y-gap="gridGap" :cols="form.grid" :style="{width: form.width, margin:'0px auto' }"><template v-for="(item, index) in form.items" :key="index"><n-form-item-gi v-if="item._hide!=true" :span="item._col" :show-feedback="false" :show-label="!(item._hideLabel === true || !form.labelShow)":label-placement="form.labelPlacement" :label-align="form.labelAlign" :label-width="form.labelWidth"><template #label>{{item._text}}<span v-if="item._required" style="color: red;"> *</span></template><component v-if="item._container && item.items" :is="buildComponent(item, renders, false)"><render-container :gridGap="gridGap" :renders="renders" :form="item" :formData="childForm(item)" :labelPlacement="item.labelPlacement" :labelAlign="item.labelAlign" /></component><component v-else-if="item._widget=='DATE'" v-model:formatted-value="rowData[item._uuid]" :is="buildComponent(item, renders, false)" /><component v-else v-model:value="rowData[item._uuid]" :is="buildComponent(item, renders, false)" /></n-form-item-gi></template></n-grid></td></tr></table><div style="margin-top: 10px; text-align: center;"><n-button size="small" :disabled="!canAdd" circle @click.stop="onAddRow">+</n-button></div></template><template v-else><n-grid :x-gap="gridGap" :y-gap="gridGap" :cols="form.grid" :style="{width: form.width, margin:'0px auto' }"><template v-for="(item, index) in form.items" :key="index"><n-form-item-gi v-if="item._hide!=true" :span="item._col" :show-feedback="false" :show-label="!(item._hideLabel === true || !form.labelShow)":label-placement="form.labelPlacement" :label-align="form.labelAlign" :label-width="form.labelWidth"><template #label>{{item._text}}<span v-if="item._required" style="color: red;"> *</span></template><component v-if="item._container && item.items" :is="buildComponent(item, renders, false)"><render-container :gridGap="gridGap" :renders="renders" :form="item" :formData="childForm(item)" :labelPlacement="item.labelPlacement" :labelAlign="item.labelAlign" /></component><component v-else-if="item._widget=='DATE'" v-model:formatted-value="formData[item._uuid]" :is="buildComponent(item, renders, false)" /><component v-else v-model:value="formData[item._uuid]" :is="buildComponent(item, renders, false)" /></n-form-item-gi></template></n-grid></template>
</template>
<script setup>import { ref, computed } from 'vue'import { ContainerProps, ContainerMixin } from '@grid-form/common/render.mixin'import { buildComponent } from '@grid-form/common'const props = defineProps(ContainerProps)const { isMultiple, canAdd, childForm, onAddRow } = ContainerMixin(props)
</script>

脚本交互

  1. 增加支持交互(单击、双击)的组件:按钮、图片
  2. 优化运行时函数:表单项数组对象增加$(致敬 JQuery😄)方法,便于快速按 ID/编号 查找内容
//找到编号为 name 的表单项(返回首个匹配值),并禁用
items.$("name").disabled = true
//找到编号为'name'、_text为'专业名称'的表单项(返回首个匹配值),并禁用
items.$({_uuid:"name", "_text":"专业名称"}).disabled = true

结语

因个人能力有限,此工具在设计、实现上存在诸多不足,仅作学习交流🙂。

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

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

相关文章

PeakCAN连接到WSL2 Debian

操作步骤 按照以下步骤进行操作&#xff1a; 在Windows下安装PeakCAN驱动并安装&#xff0c;地址是https://www.peak-system.com/PCAN-USB.199.0.html?&L1 在Windows下安装usbipd&#xff0c;地址是https://github.com/dorssel/usbipd-win/releases&#xff0c;最新版是…

sqli-labs-master less-1 详解

目录 关于MySQL的一些常识 information_schema 常用的函数 sqli-labs-master less-1 分析PHP源码 测试 关于MySQL的一些常识 information_schema information_schema 是 MySQL 数据库中的一个元数据&#xff08;metadata&#xff09;数据库&#xff0c;它包含…

计数排序(六)——计数排序及排序总结

目录 一.前言 二.归并小补充 三.计数排序 操作步骤&#xff1a; 代码部分&#xff1a; 四.稳定性的概念&#xff1a; 五.排序大总结&#xff1a; ​六.结语 一.前言 我们已经进入排序的尾篇了&#xff0c;本篇主要讲述计数排序以及汇总各类排序的特点。码字不易&#x…

[Tcpdump] 网络抓包工具使用教程

往期回顾 海思 tcpdump 移植开发详解海思 tcpdump 移植开发详解 前言 上一节&#xff0c;我们已经讲解了在海思平台如何基于静态库生成 tcpdump 工具&#xff0c;本节将作为上一节的拓展内容。 一、tcpdump 简介 「 tcpdump 」是一款强大的网络抓包工具&#xff0c;它基于…

国标GB/T 28181详解:GB/T28181基本注册流程和注销流程

目 录 一、基本要求 二、注册流程 三、注销流程 四、产品说明 五、参考 一、基本要求 根据《GB/T 28181-2022》第9章关于注册和注销的描述&#xff0c;GB28181的注册和注销应满足下面这些要求&#xff1a; SIP 客户端网关、SIP 设备、联网系统等 SIP 代理…

【command】使用nr简化npm run命令

参考文章 添加 alias nrnpm run通过alias启动命令可以帮助我们节省运行项目输入命令的时间 $ cd ~ $ vim .bash_profile $ source ~/.bashrc

一进一出模拟量信号隔离变送器

一进一出模拟量信号隔离变送器 捷晟达科技推出一进一出模拟量信号隔离变送器 深圳捷晟达科技推出一款具有隔离,放大,转换保护功能的一进一出的小型隔离变送器设备,该设备可以把模拟量(4-20mA/0-10V等)标准信号转换用户需要的信号,该产品具有抗EMC干扰,可以有效的保护后级设备安…

github添加 SSH 密钥

1 打开终端 输入 ssh-keygen -t rsa -b 4096 -C "github邮箱地址"如果不需要密码可以一路回车 出现这个页面就是生存成功了 open ~/.ssh // 打开.ssh 找到id_rsa.pub复制出内容新建ssh密钥输入内容,保存即可

PawSQL更新 | 新增18个SQL性能审核重写规则

PawSQL最新版本针对DML和DQL新增了审核和重写优化规则共计33个&#xff0c;整体的规则数目达到了83个&#xff0c;覆盖了正确性&#xff0c;安全性、可维护性、性能四个方面的SQL质量问题&#xff0c;并提供了优化建议&#xff0c;已经形成比较完善的针对数据操作的SQL质量审查…

构建高效外卖系统:利用Spring Boot框架实现

在当今快节奏的生活中&#xff0c;外卖系统已经成为人们生活中不可或缺的一部分。为了构建一个高效、可靠的外卖系统&#xff0c;我们可以利用Spring Boot框架来实现。本文将介绍如何利用Spring Boot框架构建一个简单但功能完善的外卖系统&#xff0c;并提供相关的技术代码示例…

关于在Tkinter + Pillow图片叠加中出现的问题

这段时间我一直在尝试对多图层图片进行一个叠加的操作&#xff0c;想用tkinter实现出来&#xff0c;先看错误 这里我其实已经选择了图片&#xff0c;但是发现是ValueError&#xff0c;我尝试断点检测但是也无动于衷&#xff0c;因为设置变量检测的时候发现变量并没有错误&…

Ubuntu 20.04 Server 使用命令行设置 IP 地址

1、编辑 /etc/netplan/ 目录下的配置文件00-installer-config.yaml (修改之前&#xff0c;把原来的文件备份) 按照对应的配置进行修改IP地址和网关 2、运行命令使其生效 sudo netplan apply 修改完成后&#xff0c;永久有效。重启后配置不会丢失