当前位置: 首页 > news >正文

Vue——formcreate表单设计器自定义组件实现(二)

前面我写过一个自定义电子签名的formcreate表单设计器组件,那时初识formcreate各种使用也颇为生疏,不过总算套出了一个组件不是。此次时隔半年又有机会接触formcreate,重新熟悉和领悟了一番各个方法和使用指南。趁热打铁将此次心得再次分享。

本次要实现的自定义组件是一个表格,表格在前端是个十分常见的组件,然而formcreate里面却没有内置,我翻了issues里面有大佬说可以直接用VxeTable来做,做不做内置都是一样的。于是沿着这个思路自己做了一番实践最终也实现了两个版本,一个是Element Table简易版,一个是VxeTable的高度定制。下面就具体说说实现方法,以及其中遇到的一些问题和解法。

Element Table实现自定义FormCreate表单设计器组件

在这里插入图片描述

自定义表头和列名

只要前端可以手动输入列名的label和value,我们就可以根据这串json,遍历实现一个表格。实现代码的代码如下:

<el-table:data="tableOptions.tableData":border="tableOptions.showBorder":show-summary="tableOptions.showSummary":summary-method="getSummaries"size="mini"style="width: fit-content"><!--多选列--><el-table-columnv-if="tableOptions.showMultiSelect"type="selection"width="50"align="center"/><!--序号列--><el-table-columnv-if="tableOptions.showIndex"type="index"label="序号"width="50"align="center"/><!--数据列--><el-table-columnv-for="column in tableOptions.tableColumns":key="column.value":label="column.label":prop="column.value"width="120"align="center"><template slot-scope="scope"><span v-if="tableOptions.readonly">{{ scope.row[column.value] }}</span><el-inputv-elsev-model="scope.row[column.value]":value="scope.row[column.value]"/></template></el-table-column></el-table><el-buttonv-if="!tableOptions.readonly"type="text"icon="el-icon-plus"@click="addRow">添加一行</el-button>

自定义组件生成规则

组件生产规则在上一篇文章中已经说过了,不熟悉的同学可以去回顾下。Vue——formcreate表单设计器自定义组件实现

这里简略说一下本次开发中新得到的一些体验和实验方法吧。

1、生成规则中如何使用自定义组件?

  • 在上一篇文章中我们将组件引入到组件生产规则js文件中,同时关联了自定义组件,代码如下:
import SignBoard from "../components/esign/SignBoard.vue";export const signboard = {rule() {return {component: SignBoard, //挂载自定义组件};},
}

这种方法相对繁琐一点,本次在git上面查询问题时,偶然看到一句话说,只要是全局引入到自定义组件都可以直接在表单设计器中直接使用,就像你使用iViewElementUI一样方便,经测试确实可行,一起来看代码;

  • 全局引入到自定义组件,直接在生成规则中使用
1、main.js 全局引入表格组件
import FormTable from "@/views/process/components/table/FormTable.vue";
Vue.component("FormTable", FormTable)2、tableRule.js 组件生产规则文件中使用
export const formTable = {rule() {return {//生成组件的名称type: "FormTable",//field formcreate生成的json文件中用了收集组件填充数据的字段名称field: "tableValue",};},
}

2、表单设计器中如何实现自定义组件的自定义属性?

自定义属性也定义在组件生成规则js文件中,写在prop()中。

export const formTable = {//拖拽组件配置项(props)的生成规则props() {return [//生成`checkbox`组件的`options`配置规则FcDesigner.makeOptionsRule("options"),{ type: "switch", field: "showSummary", title: "是否显示表尾合计" },];}
};

有一些公共默认属性,通常是标签宽度,标签位置,表单尺寸等。如果我们需要一些自定义属性需要自己在组件规则文件的props() 中添加一个对象,type可以是输入框,开关,计数器,单选,下拉框等基本控件,可以是TableOptions,Struct高级输入等。
基础控件使用参考:http://www.form-create.com/v2/element-ui/
高级控件使用参考:https://gitee.com/xaboy/form-create-designer/tree/master/src/components
当你不知道你所使用的控件怎么在组件规则里面使用时,可以找官方提供的组件源码来看下,参观里面的配置即可。
官方组件生成规则参考:https://gitee.com/xaboy/form-create-designer/tree/master/src/config/rule

3、Table组件自定义属性

Alt
如上图,Table中增加了设置表头列名,是否显示表格边框,表尾合计(且支持自定义合计列),显示序列号,显示多选列,初始表格行数等属性,其中开关按钮,计数器组件等都比较简单,可以设置默认值,控制属性等,直接参考官方代码就好。我会详细说明下StructButtonTableOption多选下拉框等实现过程。

Struct

Struct是一个点击按钮,弹出一个dialog,可以自由编写输入一串json的一个组件。效果如下:
这样我们自定义属性处理的内容就可以非常灵活了,比如我们希望根据一串json配置自动生成一个自定义表格,这个下一节展开说。或者说我们可以定义表格初始化显示的数据等等;
在这里插入图片描述

{type: 'Struct',field: 'headers',title: '设置上传的请求头部',props: {defaultValue: {}}
}
Button

上面的Struct组件是点击一个按钮弹出一个dialog,有的同学可能说,我不想点击按钮弹出dialog,我想做其他自定义操作可以吗?当然可以啦~只不过官方并没有给出button的使用说明,经过研究和实践,我们需要使用原生el-button同时为button绑定click事件就能进行自定义操作了。
官方源码参考:https://gitee.com/xaboy/form-create-designer/blob/master/src/config/base/field.js

这里我们来实现一个点击按钮给表格新增一行的小功能。实现思路为:

  1. 点击按钮更新表格行数,这里我们需要先获取表格原本的行数,然后给其+1;
  2. 自定义组件中监听表格行数属性的变化,然后重新绘制表格行数;

根据这个思路一起来看下这个代码如何实现:
1、给按钮设置点击事件并更新表格行数

 { type: "hidden", field: "rowNums", value: 1 },{type: "el-button",props: {type: "primary",size: "mini",icon: "el-icon-delete"},inject: true,on: {click({ $f }) {//更新组件规则,否则数据修改不会更新UIlet rowNums = $f.getRule("rowNums").value$f.updateRule("rowNums", {value: rowNums+1,});const rule = $f.rule;if (rule) {rule.addRow = true;$f.updateRule(rule);}}},native: true,children: ["新增一行"]},

这里有一些知识点需要说明下:
1、如何获取表格的行数?
这里我们通过一个隐藏字段来收集表格的行数;
2、如何更新表格的行数?
首先我们需要获取表格行数的属性,并将其更新。注意此处只修改属性值是没用的,我们需要将这个规则进行刷新,否则不会更新Ui。
组件规则的操作可参考:更新指定规则
3、$f是什么?
这里参考下官方文档的解释:获取$f,他应该代表的就是FCDesigner对象,有兴趣的同学可以打印看下他的结构。

2、根据表格行数更新Ui
修改完表格行数后,我们需要在UI组件中监听这个数值的变化并根据这个数值更新UI。

props: {formCreateInject: {type: Object,required: true}
},watch: {//formCreateInject为组件生成时会给自定义组件注入的参数"formCreateInject.rule.props": {handler() {//当表单设计器的自定义设置规则修改时,同步更新FormCreateDesiger中的自定义组件this.update();},deep: true},},update(){let rowNums = this.formCreateInject.rule.props?.rowNums ?? 1;for (let i = 0; i < rowNums - this.tableOptions.tableData.length; i++) {this.tableOptions.tableData.push({});}
}

实现过程比较简单,其中有一点解释下,我们注意下这个formCreateInject这个对象为表单设计器生成自定义组件时自动注入的参数,这个属性需在UI组件的自定义属性中定义,否则没法实现组件数据的回传等等;
官方说明:预定义 props

TableOption

TableOption,根据名字就可以知道它是一个表格相关组件,如下图:
在这里插入图片描述

点击添加按钮可以新增一行,在Table组件中就是用这个组件来实现自定义列名和表头的。
官网源码参考:https://gitee.com/xaboy/form-create-designer/blob/master/src/utils/index.js

{type: "TableOptions",field: "columns",title: "设置表头和列名",props: {defaultValue: []},
},

输入完成后我们将得到如下json:

[{ label: 'seq', value: ‘’},
], //数据列

然后根据这个数据实现Ui组件中的列的绘制。

组件之间的联动

这一节将介绍如何实现自定义行尾合计列的实现方式。

  1. 首先需添加一个下拉框来实现自定义列的选择;
  2. 其次需要将已选的列回传给Table组件,这里就用到了组件属性之间的联动,可参考官方文档:组件联动概括来说就是,我们可以在某个组件规则的前后,甚至子级增加对另外一个组件规则的控制;在本例中,我们需要用TableOption控制表尾合计列多选拉下框的显示;所以合起来的代码应该为
{type: "TableOptions",field: "columns",title: "设置表头和列名",props: {defaultValue: []},//组件联动:设置完列名以后,更新显示合计列的多选下拉列表control: [{handle(val, fApi) {sumColums = val;sumColumsVal = [];if (sumColums?.length > 0) {sumColums.forEach(item => {sumColumsVal.push(item.value);});}//更新组件规则,否则数据修改不会更新UIfApi.updateRule("sumColumns", {value: sumColumsVal,options: sumColums});return val?.length > 0;},append: "showSummary", //在某个组件后插入rule: [{type: "select",field: "sumColumns",title: "自定义表尾合计列",value: sumColumsVal,//选择的数据,类型为【】options: sumColums,//选项数据props: {multiple: true}}]}]
},
{ type: "switch", field: "showSummary", title: "是否显示表尾合计" },

Ui组件中只计算某些列的合计实现如下:

//自定义合计方法,可以选择只计算某些列的合计,不需要计算的返回空
getSummaries(param) {//需要计算合计的列let sumColumns = this.formCreateInject.rule.props?.sumColumns;const { columns, data } = param;const sums = [];columns.forEach((column, index) => {if (index === 0) {sums[index] = "合计";return;}let values = [];if (sumColumns?.length > 0) {//只计算选中列的合计values = data.map(item => {return sumColumns.indexOf(column.property) != -1? Number(item[column.property]): "-";});} else {//默认计算所有列的合计values = data.map(item => Number(item[column.property]));}if (!values.every(value => isNaN(value))) {sums[index] = values.reduce((prev, curr) => {const value = Number(curr);if (!isNaN(value)) {return prev + curr;} else {return prev;}}, 0);} else {sums[index] = "";}});return sums;
}

VxeTable实现自定义FormCreate表单设计器组件

前面一节自己实现表格只能是比较简单的样式和效果,如果我想要更复杂的表格呢?如果只是增加更多的自定义属性来控制表格的实现,那么必定增加运营配置人员的负担。此时VxeTable就为我们提供一个强大的功能,只要写好高级配置的json,代码中就可以根据这个json直接生成效果更为丰富的表格。

VxeTable官方文档参考:https://vxetable.cn/#/table/start/install
本节我们用到的是VxeTable高级表格的能力,大概预览下高级表格的实现代码:

<template><div><vxe-grid v-bind="gridOptions"/></div>
</template><script lang="ts" setup>
import { reactive } from 'vue'
import { VxeGridProps } from 'vxe-table'interface RowVO {id: numbername: stringnickname: stringrole: stringsex: stringage: numberaddress: string
}const gridOptions = reactive<VxeGridProps<RowVO>>({border: true,height: 300,align: null,columnConfig: {resizable: true},columns: [{ type: 'seq', width: 50 },{ field: 'name', title: 'name' },{ field: 'sex', title: 'sex' },{ field: 'address', title: 'Address' }],toolbarConfig: {slots: {buttons: 'toolbar_buttons'}},data: [{ id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },{ id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },{ id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }]
})
</script>

由上述代码可见,Vxetable的代码非常简洁,只需要一个option配置项就可以来,那么沿着这个思路,我们就可以把option放在自定义属性中用Struct来进行编辑,就能快速实现不同效果的表格,这个方法对配置人员对要求较高T=T

实现过程不难,代码就不放了。有兴趣的同学可以自行实践。

本篇文章介绍的内容较多,相信经过这篇介绍,以后再有自定义组件的需求时你一定都能游刃有余了。也有些盲点可能没扫到,后续有研究会继续更新的。有好的思路也欢迎评论区留言探讨~

相关文章:

Vue——formcreate表单设计器自定义组件实现(二)

前面我写过一个自定义电子签名的formcreate表单设计器组件&#xff0c;那时初识formcreate各种使用也颇为生疏&#xff0c;不过总算套出了一个组件不是。此次时隔半年又有机会接触formcreate&#xff0c;重新熟悉和领悟了一番各个方法和使用指南。趁热打铁将此次心得再次分享。…...

人脸验证(Face verification) 和 人脸识别(Face recognition) 的区别

人脸验证(Face verification) 和 人脸识别(Face recognition) 的区别 Face verification 和 Face recognition 都是人脸识别的技术&#xff0c;但是它们的应用和目的不同。 Face verification&#xff08;人脸验证&#xff09;是指通过比对两张人脸图像&#xff0c;判断它们是…...

前端如何打开钉钉(如何唤起注册表中路径与软件路径不关联的软件)

在前端唤起本地应用时&#xff0c;我查询了资料&#xff0c;在注册表中找到腾讯视频会议的注册表情况&#xff0c;如下&#xff1a; 在前端代码中加入 window.location.href"wemeet:"; 就可以直接唤起腾讯视频会议&#xff0c;但是我无法唤起钉钉 之所以会这样&…...

数据可视化入门指南

数据可视化是一种将抽象的数值和数据转换为易于理解的图像的方法。它可以帮助人们更好地理解数据的含义&#xff0c;并且可以揭示数据中可能被忽视的模式和趋势。本文将为你提供一个简单的数据可视化入门指南。 为什么数据可视化重要&#xff1f; 在我们的生活中&#xff0c;数…...

React 18 响应事件

参考文章 响应事件 使用 React 可以在 JSX 中添加 事件处理函数。其中事件处理函数为自定义函数&#xff0c;它将在响应交互&#xff08;如点击、悬停、表单输入框获得焦点等&#xff09;时触发。 添加事件处理函数 如需添加一个事件处理函数&#xff0c;需要先定义一个函数…...

面试总结-c++

1该吹牛逼吹牛逼。在自己能说出个所以然的情况下&#xff0c;该吹就吹&#xff0c;不吹没工作&#xff0c;吹了有希望。 比如 c组长&#xff0c;确有其事&#xff0c;但是挺唬人。说自己在北京定居也是侧面吹牛逼&#xff0c;证明自己的能力。还有媳妇在研究所。 2.对自己做过…...

Spring(九) - 解惑 spring 嵌套事务.2

1. 事务传播特性 在所有使用 spring 的应用中, 声明式事务管理可能是使用率最高的功能了, 但是, 从我观察到的情况看,绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义, 让我们来看一下 TransactionDefinition 接口中的定义 Java代码 /** * Support a cu…...

Android Studio API 33 获取当前连接的WIFI名称

常规流程失败流程 常规流程 以下内容在 API 33 成功实现&#xff0c;低版本API还请自行尝试&#xff08;仅推荐 API 29 - 33 用户食用&#xff09; 先&#xff08;至少&#xff09;添加以下权限到你的 AndroidManifest.xml 文件 <uses-permission android:name"andr…...

ICCV 2023 | 半监督三维目标检测新SOTA:密集匹配和量化补偿

论文链接&#xff1a;https://arxiv.org/abs/2304.13031 开源代码仓库地址&#xff1a;https://github.com/AIR-DISCOVER/DQS3D 方法效果对比图&#xff1a;有效在半监督情况下处理临近小物体 01. 简介 本文旨在解决三维室内场景中高昂的标注成本问题&#xff0c;特别关注半监…...

python+django+mysql项目实践三(用户管理)

python项目实践 环境说明: Pycharm 开发环境 Django 前端 MySQL 数据库 Navicat 数据库管理 用户列表展示 urls view models html <!DOCTYPE html> <html...

Java多线程 | 操作线程的方法详解

文章目录 一、线程的启动1.1 start()方法 二、线程的休眠与中断2.1 Thread.sleep()方法2.2 interrupt()方法 三、线程的等待与唤醒3.1 wait()方法3.2 Object类的notify()和notifyAll()方法3.3 await()和signal()方法3.4 使用join()方法等待线程执行完成 四、线程的状态控制与管…...

【ConcurrentHashMap1.7源码】十分钟带你深入ConcurrentHashMap并发解析

ConcurrentHashMap1.7源码 四个核心要点 初始化PUT扩容GET Unsafe 初始化 五个构造方法 /*** Creates a new, empty map with the default initial table size (16).*/public ConcurrentHashMap() {}/*** Creates a new, empty map with an initial table size* accommodati…...

程序框架-事件中心模块-观察者模式

一、观察者模式 1.1 观察者模式定义 意图&#xff1a; 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变是&#xff0c;所有依赖于它的对象都能得到通知并自动更新。 适用性&#xff1a; 当一个对象状态的改变需要改变其他对象&#xff0c; 或实际对…...

通过AOP的ProceedingJoinPoint获取方法信息

文章目录 ProceedingJoinPoint用法 ProceedingJoinPoint用法 获得切点对应的方法&#xff08;Method&#xff09; 本处Method指的是java.lang.reflect.Method 若切入点表达式是方法&#xff0c;则获得的是切入点方法的信息。若切入点表达式是注解&#xff0c;则获得的是使用了…...

【JavaSE】初步认识类和对象

【本节目标】 1. 掌握类的定义方式以及对象的实例化 2. 掌握类中的成员变量和成员方法的使用 3. 掌握对象的整个初始化过程 目录 1. 面向对象的初步认知 2. 类定义和使用 3. 类的实例化 4. this引用 1. 面向对象的初步认知 1.1 什么是面向对象 Java是一门纯面向对象的语…...

python中的matplotlib画饼图(数据分析与可视化)

直接开始 1、先安装pandas和matplotlib pip install pandas pip install matplotlib2、然后在py文件中导入 import pandas as pd import matplotlib.pyplot as plt3、然后直接写代码 import pandas as pd import matplotlib.pyplot as pltpd.set_option("max_columns&…...

用Rust实现23种设计模式之 职责链模式

关注我&#xff0c;学习Rust不迷路&#xff01;&#xff01; 优点 解耦&#xff1a;职责链模式将请求发送者和接收者解耦&#xff0c;使得多个对象都有机会处理请求&#xff0c;而不是将请求的发送者和接收者紧密耦合在一起。灵活性&#xff1a;可以动态地改变或扩展处理请求…...

进销存管理中的技术创新和数字化转型

在进销存管理中&#xff0c;技术创新和数字化转型可以通过以下具体的应用案例来实现&#xff1a; 自动化仓储系统&#xff1a;利用自动化技术和机器人系统来管理仓库操作&#xff0c;包括货物的装卸、分拣和存储。这可以提高仓库的运作效率&#xff0c;减少人力成本&#xff0…...

与“云”共舞,联想凌拓的新科技与新突破

伴随着数字经济的高速发展&#xff0c;IT信息技术在数字中国建设中起到的驱动和支撑作用也愈发凸显。特别是2023年人工智能和ChatGPT在全球的持续火爆&#xff0c;更是为整个IT产业注入了澎湃动力。那么面对日新月异的IT信息技术&#xff0c;再结合疫情之后截然不同的经济环境和…...

【超细节】Vue3组件事件怎么声明,defineEmits与emit

目录 前言 一、基本语法 1. 子组件触发 2. 父组件监听 二、 事件参数 1. 传值 2. 接收值 三、 事件校验 四、注意事项 前言 组件事件是 Vue 组件之间进行通信的一种方式。它允许一个组件触发一个自定义事件&#xff0c;并且其他组件可以监听并响应这个事件。 一、基本…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...