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-column
        v-if="tableOptions.showMultiSelect"
        type="selection"
        width="50"
        align="center"
      />

      <!--序号列-->
      <el-table-column
        v-if="tableOptions.showIndex"
        type="index"
        label="序号"
        width="50"
        align="center"
      />

      <!--数据列-->
      <el-table-column
        v-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-input
            v-else
            v-model="scope.row[column.value]"
            :value="scope.row[column.value]"
          />
        </template>
      </el-table-column>
    </el-table>

    <el-button
      v-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 }) {
       //更新组件规则,否则数据修改不会更新UI
       let 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);
	         });
	       }
	       //更新组件规则,否则数据修改不会更新UI
	       fApi.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: number
  name: string
  nickname: string
  role: string
  sex: string
  age: number
  address: 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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

身体原来是一份宝贵的“情绪地图”, 疾病都在教导我们如何与世界相处

当我们生病时 很多时候&#xff0c;是一个契机 让我们来倾听自己内心的压抑的真实 聆听身体的声音 身体能够教会我们如何对待情绪 进而教导我们如何与世界相处 -1- 身体上&#xff0c;有你的情绪地图 皮肤是身体的镜子&#xff0c;身体则是心灵的镜子。生病&#xff0c…

什么是微服务

微服务的架构特征&#xff1a; 单一职责&#xff1a;微服务拆分粒度更小&#xff0c;每一个服务都对应唯一的业务能力&#xff0c;做到单一职责自治&#xff1a;团队独立、技术独立、数据独立&#xff0c;独立部署和交付面向服务&#xff1a;服务提供统一标准的接口&#xff0…

《Java-SE-第二十八章》之CAS

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水平很有限&…

AI绘图实战(十二):让AI设计LOGO/图标/标识 | Stable Diffusion成为设计师生产力工具

S&#xff1a;AI能取代设计师么&#xff1f; I &#xff1a;至少在设计行业&#xff0c;目前AI扮演的主要角色还是超级工具&#xff0c;要顶替&#xff1f;除非甲方对设计效果无所畏惧~~ 预先学习&#xff1a; 安装及其问题解决参考&#xff1a;《Windows安装Stable Diffusion …

Kali部署dvwa和pikachu靶场

kali换源 进入 vim /etc/apt/sources.list deb https://mirrors.aliyun.com/kali kali-rolling main non-free contrib deb-src https://mirrors.aliyun.com/kali kali-rolling main non-free contrib替换完后更新源 apt-get upadteDVWA靶场环境搭建 使用git从github上把DV…

项目中引用svg图标,公共组件SvgIcon使用,注册全局组件,使用自定义插件注册全局组件

在开发项目的时候经常会用到svg矢量图,而且我们使用SVG以后&#xff0c;页面上加载的不再是图片资源, 这对页面性能来说是个很大的提升&#xff0c;而且我们SVG文件比img要小的很多&#xff0c;放在项目中几乎不占用资源。 1、安装依赖插件 pnpm install vite-plugin-svg-ic…

以产品经理的角度去讲解原型图---会议OA项目

目录 一.前言 二.原型图 2.1 原型图是什么 3.1 原型图的作用 三.演示讲解 3.1 项目背景 3.2 项目介绍 3.2.1 会议管理&#xff08;会议的发起&#xff0c;通知&#xff09; 3.2.2 投票管理&#xff08;会议的流程重大决策记录&#xff09; 3.2.3 会议室管理 3.2.4 系统管…

2023年第三届工业自动化、机器人与控制工程国际会议 | IET独立出版 | EI检索

会议简介 Brief Introduction 2023年第三届工业自动化、机器人与控制工程国际会议&#xff08;IARCE 2023&#xff09; 会议时间&#xff1a;2023年10月27 -30日 召开地点&#xff1a;中国成都 大会官网&#xff1a;www.iarce.org 2023年第三届工业自动化、机器人与控制工程国际…

Android 获取网络连接状态新方法

一. 问题背景 Android12上&#xff0c;有的app模块判断当前网络的类型和连接状态时&#xff0c;还是使用的旧的API&#xff0c;导致返回的结果不准确&#xff0c;影响代码逻辑判断&#xff0c;本篇文章就这一问题&#xff0c;整理一下判断网络类型和连接状态的新方法。 二. 原因…

Selenium上传文件有多少种方式?不信你有我全!

Selenium 封装了现成的文件上传操作。但是随着现代前端框架的发展&#xff0c;文件上传的方式越来越多样。而有一些文件上传的控件&#xff0c;要做自动化控制会更复杂一些&#xff0c;这篇文章主要讨论在复杂情况下&#xff0c;如何通过自动化完成文件上传 input 元素上传文件…

go env 配置(环境变量)说明

前提&#xff1a;已经安装好 golang 可正确的运行下面这段命令&#xff0c;来查看 go 的配置&#xff1a; go env 输出示例&#xff1a; 以上是我本地(windows)环境下输出的配置信息(环境变量) 我们这次就针对每个配置信息进行一个说明&#xff0c;具体到每个字段是什么意思…

前端(十一)——Vue vs. React:两大前端框架的深度对比与分析

&#x1f60a;博主&#xff1a;小猫娃来啦 &#x1f60a;文章核心&#xff1a;Vue vs. React&#xff1a;两大前端框架的深度对比与分析 文章目录 前言概述原理与设计思想算法生态系统与社区支持API与语法性能与优化开发体验与工程化对比总结结语 前言 在当今快速发展的前端领…

iOS——Block回调

先跟着我实现最简单的 Block 回调传参的使用&#xff0c;如果你能举一反三&#xff0c;基本上可以满足了 OC 中的开发需求。已经实现的同学可以跳到下一节。 首先解释一下我们例子要实现什么功能&#xff08;其实是烂大街又最形象的例子&#xff09;&#xff1a; 有两个视图控…

性能测试怎么做?测试工具怎么选择?

在当前软件测试行业&#xff0c;熟练掌握性能测试已经是测试工程师们面试的敲门砖了&#xff0c;当然还有很多测试朋友们每天的工作更多的是点点点&#xff0c;性能方面可能也只是做过简单的并发测试&#xff0c;对于编写脚本&#xff0c;搭建环境方面也比较陌生。今天这篇文章…

【力扣刷题 | 第二十四天】

目录 前言&#xff1a; 416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 总结 前言&#xff1a; 今晚我们爆刷动态规划类型的题目。 416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这…

第一百二十天学习记录::计算机硬件技术基础:存储器及存储管理

分级存储器系统 存储器从内到外分为四级&#xff1a;内部寄存器、高速缓冲存储器、内存储器和外存储器。它们在存取速度上逐级递减&#xff0c;在存储容量上逐级递增。 内部寄存器 内部寄存器是计算机处理器内部的一种高速缓存&#xff0c;是用来存储临时数据和指令等信息的…

stm32 mpu6050 cubemx DMP法读取角度

文章目录 前言一、相关文件二、cubemx配置三、代码变量初始化主循环 总结 前言 文件 记录使用dmp库来读取mpu6050的角度。 这是参考文件 参考1–主要参考 github参考 参考2 参考三 一、相关文件 相关文件在这里下载&#xff08;未填&#xff0c;不过可以在上面的git中下载&a…

【iOS】锁

线程安全 当一个线程访问数据的时候&#xff0c;其他的线程不能对其进行访问&#xff0c;直到该线程访问完毕。简单来讲就是在同一时刻&#xff0c;对同一个数据操作的线程只有一个。而线程不安全&#xff0c;则是在同一时刻可以有多个线程对该数据进行访问&#xff0c;从而得…

sql语句字符函数,数学函数

一、trim&#xff08;&#xff09;去掉前后单元格 SELECT LENGTH(TRIM( 张三 )) AS 姓名 trim&#xff08;aa from bb) 除掉bb中前后包含的aa&#xff0c;中间的保留 SELECT TRIM(班 FROM class) AS 姓名 FROM user_test 二、lpad&#xff08;&#xff09;用指定字符做左…

嘉楠勘智k230开发板上手记录(二)

上次成功在k230上烧录sdk&#xff0c;这次准备实现hello world和ssh scp远程k230 一、PC连接k230 1. 初步准备 首先下载串口工具PuTTY&#xff0c;这个我个人感觉比较方便。 准备两根USB type-C数据线&#xff0c;一根连电源&#xff0c;一根连串口调试。还有Type C公头转网…