设计可编辑表格组件

前言

什么是可编辑表格呢?简单来说就是在一个表格里面进行表单操作,执行增删改查。这在一些后台管理系统中是尤为常见的。
在这里插入图片描述
今天我们根据vue2 + element-ui来设计一个表单表格组件。(不涉及完整代码,想要使用完整功能可以看底部连接)

开始设计

1.表单组件

首先我们思考表格里面的表单元素应该如何实现。在用户使用的时候,我们希望用户传入一个指定的类型自动去匹配对应的表单组件。那我们就应该将所有类型做一个集成,并分别给他们一个类型名称。

当然,为了最大程度为他们保留在element-ui已经实现的属性与方法,formEle肯定接收的是一个对象,对象里面包含了他要展示的组件类型,一些原element-ui的属性方法,我们使用$attrs便可以直接将属性绑定到element-ui的表单组件上。

我们为这个表单元素组件取名为formEle,并最大程度为他们保留在element-ui已经实现的属性与方法。当然我们也可以修改一下一些常用属性的默认值,例如打开clearable清除属性,设置placeholder默认值。

下面是部分代码

<template>
  <el-input
    v-if="formType === 'input'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :clearable="clearable"
    :placeholder="placeholder"
  >
    <template v-for="(value, name) in $slots" #[name]>
      <slot :name="name"> </slot>
    </template>
  </el-input>
  <el-input-number
    v-else-if="formType === 'inputNumber'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :placeholder="placeholder"
  >
    <template v-for="(value, name) in $slots" #[name]>
      <slot :name="name"> </slot>
    </template>
  </el-input-number>
  <el-select
    v-else-if="formType === 'select'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :clearable="clearable"
    :placeholder="placeholder"
  >
    <el-option
      v-for="item in options"
      v-bind="item"
      :key="item.value"
    ></el-option>
  </el-select>
  <el-date-picker
    v-else-if="formType === 'datePicker'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :placeholder="placeholder"
    :endPlaceholder="endPlaceholder"
    :startPlaceholder="startPlaceholder"
  >
  </el-date-picker>
  <el-time-select
    v-else-if="formType === 'timeSelect'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :placeholder="placeholder"
  >
  </el-time-select>
  <el-time-picker
    v-else-if="formType === 'timePicker'"
    v-model="localValue"
    v-bind="$attrs"
    v-on="$listeners"
    :placeholder="placeholder"
    :endPlaceholder="endPlaceholder"
    :startPlaceholder="startPlaceholder"
  >
  </el-time-picker>
  <el-switch
    v-else-if="formType === 'switch'"
    v-model="localValue"
    v-bind="$attrs"
    :placeholder="placeholder"
  >
  </el-switch>
  <el-cascader
    v-else-if="formType === 'cascader'"
    v-model="localValue"
    :options="options"
    ref="cascader"
    v-bind="$attrs"
    v-on="$listeners"
    :placeholder="placeholder"
  ></el-cascader>
</template>

<script>
export default {
  name: 'ClFormEle',
  props: {
    // 表单类型
    formType: {
      type: String,
      default: 'input'
    },
    modelValue: null,
    options: {
      type: Array,
      default: () => []
    }
  },
  model: {
    prop: 'modelValue',
    event: 'editModelValue'
  },
  computed: {
    localValue: {
      get() {
        return this.modelValue
      },
      set(val) {
        this.$emit('editModelValue', val)
      }
    },
    clearable() {
      return this.$attrs.clearable === false ? false : true
    },
    placeholder() {
      let text = '请选择'
      if (this.formType === 'input') {
        text = '请输入'
      }
      return this.$attrs.placeholder || text + (this.$attrs.label || '')
    },
    rangeSeparator() {
      return this.$attrs.rangeSeparator || '至'
    },
    startPlaceholder() {
      if (this.formType === 'datePicker') {
        return this.$attrs.startPlaceholder || '开始日期'
      } else {
        return this.$attrs.startPlaceholder || '开始时间'
      }
    },
    endPlaceholder() {
      if (this.formType === 'datePicker') {
        return this.$attrs.startPlaceholder || '结束日期'
      } else {
        return this.$attrs.startPlaceholder || '结束时间'
      }
    }
  },
  methods: {
    // 获取级联组件的回显值
    getCasLabelcader() {
      this.$nextTick(() => {
        return this.$refs.cascader?.inputValue
      })
    }
  }
}
</script>

<style lang="less" scoped>
.el-input {
  width: 100%;
  height: 30px;
}
.el-select {
  width: 100%;
}
.el-date-editor {
  width: 100%;
}
</style>

需要注意的是我们还需要将element-ui组件的插槽位置预留出来。

2.考虑表格组件

首先我们要想到我们可能会使用表单组件的校验等功能,那么在最外层就一定需要el-form来包裹表格组件。

其次是表单组件上model的绑定值的选择。可以预料的是我们最终绑定的数据一定是一个数组格式的。因为表格肯定不会只有一条数据。但是我们又无法在表单的model属性上绑定数组,所以我们可以将数组封装为数组对象的格式。

 <!-- modelValueCom 为表格数据 -->
<el-form ref="formRef" :model="{ formData: modelValueCom }">

接下来我们将对列的数据进行处理。列的数据肯定也是一个数组结构的,每列我们分为两个板块,一个是用在el-table-column上的属性值,一个则是内部表单内容的属性值。为了方便区分,我们将采用一些数据格式:

[
  {
    prop: 'name',
    label: '姓名',
    minWidth: '200px',
    formEle: {
      formType: 'input'
    }
  }
]

上面的formEle对象就行将来需要用在表单组件上的属性值,而其他属性则是直接作用在el-table-column上的。

<el-table-column
	v-for="columItem in columList"
	:key="columItem.prop"
	v-bind="getColumnAttr(columItem)"
>

getColumnAttr方法的作用就是剔除formEle属性

接着就是关于表单组件的使用了。既然我们需要表单的校验方法,我们就需要el-form-item组件来包裹表单组件,而组件上最重要的prop属性则可以直接在上面的列数据中获取,注意因为数据是数组,我们需要使用下标绑定到具体的哪条数据上,label属性我们则可以直接省略,因为我们已经有表头来展示了。

<el-form-item
   v-if="row.isEdit"
   :prop="'formData.' + $index + '.' + columItem.prop"
   :rules="columItem.formEle?.rules"
>

说到表头我们可能需要想到为他添加必填校验的表示符,我们在formEle里面加入showRequiredIcon属性判断是否需要展示必填校验。
在这里插入图片描述

<el-table-column
  v-for="columItem in columList"
  :key="columItem.prop"
  v-bind="getColumnAttr(columItem)"
>
  <template #default="{ row, $index }">
    <el-form-item
      v-if="row.isEdit"
      :prop="'formData.' + $index + '.' + columItem.prop"
      :rules="columItem.formEle?.rules"
    >
      <ClFormEle
        v-model="row[columItem.prop]"
        v-bind="columItem.formEle"
        v-on="eventMap[columItem.prop]"
        :label="columItem.label"
      ></ClFormEle>
    </el-form-item>
    <!-- getLabel方法用于回显,解析一些下拉,级联,时间等 -->
    <span v-else>{{
      getLabel(
        getFormType(columItem),
        columItem,
        row[columItem.prop],
        $index
      )
    }}</span>
  </template>
  <template #header>
    <span v-if="columItem.formEle?.showRequiredIcon" class="required_icon"
      >*</span
    >
    {{ columItem.label }}
  </template>
</el-table-column>

最后我们应该还需要有一列操作按钮对行数据进行修改,保存,删除等操作。修改,保存就是修改表格数据的isEdit属性,让在表单元素与span展示中切换。

<el-table-column v-bind="btnColCpd">
  <template #default="{ row, $index: index, column }">
    <slot name="endColumn" :data="{ row, index, column }">
      <el-button
        v-if="!row.isEdit"
        type="text"
        icon="el-icon-edit"
        @click.native.stop="rowEdit(index)"
        >修改</el-button
      >
      <el-button
        v-else
        type="text"
        icon="el-icon-check"
        @click.native.stop="saveRow(index)"
        >保存</el-button
      >
      <el-popconfirm
        v-if="isDelBtnTip"
        :title="delBtnTip"
        @confirm="delRow(index)"
      >
        <el-button
          type="text"
          icon="el-icon-delete"
          class="del_btn_text"
          slot="reference"
          >删除</el-button
        >
      </el-popconfirm>
      <el-button
        v-else
        type="text"
        icon="el-icon-delete"
        class="del_btn_text"
        slot="reference"
        @click.native.stop="delRow(index)"
        >删除</el-button
      >
    </slot>
  </template>
</el-table-column>

btnColCpd是一个关于最后一列属性配置对象,我们可以的使用element-ui里面el-table-column组件的属性来控制最后一列。

到这一个简单的表单组件结构就基本实现了。

当然,上面的设计还有很多的缺陷,比如表单组件的方法该如何绑定,各个表单组件插槽该如何抛出,表单的校验可不可以在离开行的时候触发,如果想要使用的组件formEle不包含怎么办等等,想要实现一个完整的表单表格组件这些都是必须要考虑的。我封装了一个较为完整的表单表格组件,大家可以在TableForm查看。

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

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

相关文章

[C语言]大小端及整形输出问题

假设在一个32位little endian 的机器上运行下面的程序&#xff0c;结果是多少 ? 1.1先看以下三个程序 #include <stdio.h> int main() {long long a 1, b 2, c 3;printf("%lld %lld %lld\n", a, b, c); // 1 2 3printf("%d %d %d %d %d %d\n&quo…

ensp创建配置环境,实现全网互访

文章目录 创建配置环境&#xff0c;实现全网互访配置步骤接入层交换机&#xff08;sw4、sw5&#xff09;划分vlan汇聚层交换机&#xff08;sw2、sw3&#xff09;配置ip地址作为vlan网关、与sw1 ip地址直连核心层交换机&#xff08;sw1&#xff09;配置ip地址与汇聚层交换机&…

echarts地图的常见用法:基本使用、区域颜色分级、水波动画、区域轮播、给地图添加背景图片和图标、3d地图、飞线图

前言 最近几天用echarts做中国地图&#xff0c;就把以前写的demo&#xff1a;在vue中实现中国地图 拿来用&#xff0c;结果到项目里直接报错了&#xff0c;后来发现是因为版本的问题&#xff0c;没办法只能从头进行踩坑了。以下内容基于vue3 和 echarts 5.32 基本使用 获取地…

java内置的数据结构

Java语言提供了许多内置的数据结构&#xff0c;包括&#xff1a; 1. 数组&#xff08;Array&#xff09;&#xff1a;数组是最基本的数据结构之一&#xff0c;它是一个有序的元素集合&#xff0c;每个元素都有一个对应的索引。在Java中&#xff0c;数组可以通过声明和初始化来创…

python学习1补充

大家好&#xff0c;这里是七七&#xff0c;这个专栏是用代码实例来学习的&#xff0c;不是去介绍很多知识的。 话不多说&#xff0c;开始今天的内容 目录 代码1 代码2 代码3 代码4 代码5 学习1的总代码 代码1 groupeddf.groupby(单品编码) result{} groupeddf.groupb…

Vue2-动态组件案例

1.component介绍 说明&#xff1a; Type: string | ComponentDefinition | ComponentConstructor Explanation: String: 如果你传递一个字符串给 is&#xff0c;它会被视为组件的名称&#xff0c;用于动态地渲染不同类型的组件。这是一个在运行时动态切换组件类型的常见用例。…

计算机组成原理学习(输入输出系统)

目录 输入输出系统&#xff08;i/o系统&#xff09; 一.现代计算机的结构 二.常见的&#xff08;I/O设备或者是外部设备&#xff09; ​ 三.主机如何与I/O设备进行交互 四.I/O控制方式简介 五.I/O系统的基本组成 输入输出系统&#xff08;i/o系统&#xff09; 一.现代计算…

嵌入式开发中的总线与时钟

总线 AHB总线 AHB的全称是"Advanced High-performance Bus",中文翻译就是"高级高性能总线"。这是一种在计算机系统中用于连接不同硬件组件的总线架构,它可以帮助这些组件之间高效地传输数据和信息。这个总线架构通常用于处理速度较快且对性能要求较高的…

VAR模型

VAR&#xff08;Vector Autoregression&#xff09;模型是一种用于时间序列分析的统计模型&#xff0c;它可以描述多个变量之间的相互关系和动态演化。VAR模型最初是由Sims&#xff08;1980&#xff09;提出的&#xff0c;广泛应用于宏观经济学、金融领域以及其他时间序列数据分…

嵌入式培训-数据结构-day23-线性表

线性表 线性表是包含若干数据元素的一个线性序列 记为&#xff1a; L(a0, ...... ai-1, ai, ai1 ...... an-1) L为表名&#xff0c;ai (0≤i≤n-1)为数据元素&#xff1b; n为表长,n>0 时&#xff0c;线性表L为非空表&#xff0c;否则为空表。 线性表L可用二元组形式描述…

Python接口测试 requests.post方法中data与json参数区别

引言 requests.post主要参数是data与json&#xff0c;这两者使用是有区别的&#xff0c;下面我详情的介绍一下使用方法。 Requests参数 1. 先可以看一下requests的源码&#xff1a; def post(url, dataNone, jsonNone, **kwargs):r"""Sends a POST request.…

缓存击穿的原因和解决方案

缓存击穿 原因&#xff1a;一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击 解决方案 1.互斥锁 优点 没有额外的内存消耗保证一致性实现简单 缺点 线程需要等待&#xff0c;性能受影响可能有死锁风险 …

Frontier ,MDPI T3系列,植物科学领域高质量期刊分级目录发布!

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; Frontier &#xff0c;MDPI T3系列&#xff0c;植物科学领域高质量期刊分级目录发布&#xff01;https://mp.weixin.qq.com/s/ukbjIgdyaza7LmKmZmy5bw 2023年3月31日&#xff0c;中国科学技术大学科研部…

Linux 定时删除过期文件

需求说明 每日凌晨0点定时删除/temp目录下的所有一个月未被访问的文件。 脚本实现 linux 终端输入crontab -e&#xff0c;添加定时任务脚本命令 [rootlocalhost ~]# crontab -e在文件末尾追加 0 0 * * * find /temp -atime 30 -exec rm -rf {} \;参数说明 命令格式&#…

Pandas-DataFtame的索引与切片(第3讲)

Pandas-DataFtame的索引与切片(第3讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

Redis与MySQL双写一致性如何保证?

前言 四月份的时候&#xff0c;有位好朋友去美团面试。他说&#xff0c;被问到Redis与MySQL双写一致性如何保证&#xff1f;这道题其实就是在问缓存和数据库在双写场景下&#xff0c;一致性是如何保证的&#xff1f;本文将跟大家一起来探讨如何回答这个问题。 谈谈一致性 一致…

Modbus转Profinet网关使用方法

Modbus转Profinet网关&#xff08;XD-MDPN100/200&#xff09;是用于将Modbus协议和Profinet协议进行转换并进行通迅的设备。Modbus转Profinet网关&#xff08;XD-MDPN100/200&#xff09;无论是新项目还是改造项目都可轻松配置完成通迅互联。 正确的安装和配置对于确保设备的正…

【SpringBoot零基础入门到项目实战①】解锁现代Java开发之门:深度探究Spring Boot的背景、目标及选择理由

文章目录 引言Spring Boot的背景和目标背景目标 为什么选择Spring Boot1. 简化配置2. 内嵌式容器3. 生态系统支持4. 大量的Starter5. 广泛的社区支持6. 适用于微服务架构7. 丰富的扩展机制 实例演示创建一个简单的Spring Boot应用 拓展与深入学习1. Spring Boot Actuator2. Spr…

UE5 C++(三)— 基本用法(生命周期、日志、基础变量)

文章目录 生命周期日志打印Outlog打印屏幕打印 基础变量类型FString、FName 和 FText&#xff0c;三者之间的区别 基础数据类型打印 忘记说了每次在Vscode修改后C脚本后&#xff0c;需要编译一下脚本&#xff0c;为了方便我是点击这里编译脚本 生命周期 Actor 生命周期官方文档…

菜鸟学习日记(python)——匿名函数

Python 使用 lambda 来创建匿名函数。 lambda 函数是一种小型、匿名的内联函数&#xff0c;它可以具有任意数量的参数&#xff0c;但只能有一个表达式。 匿名函数的一般格式如下&#xff1a; lambda 参数列表:表达式 表达式用于计算并返回函数结果 lambda 函数通常用于编写…