Element UI el-table form 表单的封装思路

news2024/11/25 20:43:15

Element UI el-table form 表单的封装思路

思路一: 将所有 form 表单类型都在 el-column-item 组件中定义好,然后根据传入的属性控制展示哪一个 form 表单类型

部分代码如下:

<template>
  <div>
    <el-row style="padding: 0 20px">
      <el-col :span="24" style="text-align: right">
        <el-button @click.native="addRow" v-if="!isOperated"
          ><i class="el-icon-plus el-icon--left"></i>新增行</el-button
        >
      </el-col>
    </el-row>
    <el-row style="padding: 20px">
      <el-table
        ref="multipleTable"
        stripe
        border
        height="250"
        :data="data"
        tooltip-effect="dark"
        style="width: 100%"
      >
        <el-table-column
          type="index"
          label="序号"
          width="50"
          align="center"
          fixed="left"
        >
        </el-table-column>
        <template v-for="(v, i) in modulsList">
          <el-table-column
            v-if="!v.hidden"
            :label="v.label"
            :prop="v.prop"
            :key="i"
            :width="v.width"
            align="center"
          >
            <template slot-scope="scope">
              <el-form-item
                :prop="
                  dataTag ? `${dataTag}.${scope.$index}.${v.prop}` : v.prop
                "
                label-width="15px"
                label=" "
                :rules="v.rules"
              >
                <template v-if="v.type === 'text'">
                  <el-input
                    type="text"
                    v-model="scope.row[v.prop]"
                    :disabled="v.disabled"
                  ></el-input>
                </template>
                <template v-else-if="v.type === 'number'">
                  <el-input-number
                    v-model="scope.row[v.prop]"
                    :min="0"
                  ></el-input-number>
                </template>
                <template v-else-if="v.type === 'textarea'">
                  <el-input
                    type="textarea"
                    :maxlength="v.maxlength"
                    :show-word-limit="v.limit"
                    v-model="scope.row[v.prop]"
                    :disabled="v.disabled"
                  ></el-input>
                </template>
                <template v-else-if="v.type === 'datePicker'">
                  <el-date-picker
                    v-model="scope.row[v.prop]"
                    type="date"
                    placeholder="选择日期"
                    value-format="timestamp"
                    :disabled="v.disabled"
                  >
                  </el-date-picker>
                </template>
                <template v-else-if="v.type === 'select'">
                  <el-select v-model="scope.row[v.prop]" placeholder="请选择">
                    <template v-for="(x, j) in v.options">
                      <el-option
                        :label="x.label"
                        :value="x.value"
                        :key="j"
                      ></el-option>
                    </template>
                  </el-select>
                </template>
                <template v-else-if="v.type === 'switch'">
                  <el-switch v-model="scope.row[v.prop]"></el-switch>
                </template>
                <template v-else-if="v.type === 'selectRemote'">
                  <el-select
                    v-model="scope.row[v.prop]"
                    filterable
                    remote
                    placeholder="请输入"
                    :remote-method="v.searchMethod"
                    @change="v.changeMethod"
                  >
                    <el-option
                      v-for="(item, i) in v.selectOption"
                      :key="i"
                      :label="item.label"
                      :value="item.value"
                    ></el-option>
                  </el-select>
                </template>
                <template v-else> </template>
              </el-form-item>
            </template>
          </el-table-column>
        </template>
        <el-table-column
          label="操作"
          width="100"
          align="center"
          fixed="right"
          v-if="!isOperated"
        >
          <template slot-scope="scope">
            <el-button type="text" size="mini" @click="deleteRow(scope.$index)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-row>
  </div>
</template>
<script>
export default {
  components: {},
  props: {
    // 展示模块
    // #description label:名称、prop:Data的对应字段、,type:类型 , default: 新增行默认值
    modulsList: {
      type: Array,
      default: () => {}
    },
    // 渲染数据
    data: {
      type: Array,
      default: () => []
    },
    // 校验标签头
    dataTag: {
      type: String,
      default: ''
    },
    isOperated: Boolean
  },
  data() {
    return {}
  },
  methods: {
    // 新增行
    addRow() {
      let addIndex = this.data.length
      let newArr = {}
      this.modulsList.forEach((v) => {
        newArr[v.prop] = v.default
      })
      this.$set(this.data, addIndex, newArr)
      console.log('新增行', this.data)
    },
    // 删除行
    deleteRow(index) {
      if (this.data.length <= 1) {
        this.$message.error('至少含有一条')
        return false
      }
      this.data.splice(index, 1)
      console.log('删除行', this.data)
    }
  },
  mounted() {
    // 至少含有一条
    if (this.data.length === 0) {
      this.addRow()
    }
  }
}
</script>
<style lang="scss" scoped>
.el-table > .el-input,
.el-textarea,
.el-select,
.el-date-editor,
.el-input-number {
  width: 100%;
}
</style>

思路二: 将所有 form 表单都单独封装,然后通过一个 js 文件 defineAsyncComponent 汇总这些单独封装的表单组件.使用的时候,通过 component is 来引入使用.

效果如下:
在这里插入图片描述

部分代码如下

汇总表单组件的 js文件代码:
import { defineAsyncComponent } from 'vue'
const formMap = {
  FInput: defineAsyncComponent(() =>
    import('@/components/form/items/fInput.vue')
  ),

  FRadio: defineAsyncComponent(() =>
    import('@/components/form/items/fRadio.vue')
  ),
  FSwitch: defineAsyncComponent(() =>
    import('@/components/form/items/fSwitch.vue')
  ),
  FSelect: defineAsyncComponent(() =>
    import('@/components/form/items/fSelect.vue')
  ),
  FCheckbox: defineAsyncComponent(() =>
    import('@/components/form/items/fCheckbox.vue')
  ),
  FDateTimePicker: defineAsyncComponent(() =>
    import('@/components/form/items/fDateTimePicker.vue')
  ),
  FSelectUser: defineAsyncComponent(() =>
    import('@/components/form/items/fSelectUser.vue')
  ),
  FPartNo: defineAsyncComponent(() =>
    import('@/components/form/items/fPartNo.vue')
  ),
  FSelectSupplier: defineAsyncComponent(() =>
    import('@/components/form/items/fSelectSupplier.vue')
  ),
  FSupplierMaster: defineAsyncComponent(() =>
    import('@/components/form/items/fSupplierMaster.vue')
  ),
  FCascader: defineAsyncComponent(() =>
    import('@/components/form/items/fCascader.vue')
  )
}

export default formMap


封装的 formTable 组件代码如下:
<template>
  <div class="formTable">
    <el-table :data="formTableList.tableData" border style="width: 100%">
      <el-table-column
        v-for="(item, index) in formTableList.tableHeader"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        align="center"
      >
        <template slot-scope="scope">
          <span v-if="item.isTitle"> {{ scope.row[item.prop] }}</span>
          <el-form
            v-if="!item.isTitle"
            ref="refForm"
            :model="scope.row"
            :rules="formTableList.formRules"
            :label-width="labelWidth"
            class="demo-form-inline"
          >
            <el-form-item :prop="item.prop" label=" ">
              <component
                :is="formMap[item.formType]"
                :meta="item.meta"
                :obj="scope.row"
              ></component>
            </el-form-item>
          </el-form>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import formMap from '@/components/form/formMap.js'
export default {
  name: 'FormTable',
  //   watch: {
  //     formTableList: {
  //       deep: true,
  //       handler(val) {
  //         console.log(val)
  //       }
  //     }
  //   },
  props: {
    formTableList: {
      type: Object,
      default() {
        return {}
      }
    },
    labelWidth: {
      type: String,
      default: 'auto'
    }
  },
  data() {
    return {
      formMap
    }
  },
  methods: {
    modelRef() {
      return this.$refs.refForm
    }
  }
}
</script>

<style lang="scss" scoped>
.formTable {
  padding-bottom: 20px;
}
::v-deep .el-select {
  width: 100%;
}
</style>

使用 formTable 组件配置项代码如下:

<FormTable
  ref="partFourModelRef"
  :formTableList="formTableList"
></FormTable>

      formTableList: {
        formRules: {
          RPN: [{ required: true, message: '请输入', trigger: ['blur'] }],
          yanzhongdu: [
            { required: true, message: '请输入', trigger: ['blur'] }
          ],
          pindu: [{ required: true, message: '请输入', trigger: ['blur'] }],
          tancedu: [{ required: true, message: '请输入', trigger: ['blur'] }]
        },
        tableHeader: [
          {
            prop: 'fangmian',
            label: '方面',
            isTitle: true,
            meta: {
              fProp: 'fangmian'
            }
          },
          {
            prop: 'RPN',
            label: 'RPN',
            formType: 'FInput',
            meta: {
              fProp: 'RPN'
            }
          },
          {
            prop: 'yanzhongdu',
            label: '严重度(S)',
            formType: 'FInput',
            meta: {
              fProp: 'yanzhongdu'
            }
          },
          {
            prop: 'pindu',
            label: '频度(O)',
            formType: 'FInput',
            meta: {
              fProp: 'pindu'
            }
          },
          {
            prop: 'tancedu',
            label: '探测度(D)',
            formType: 'FInput',
            meta: {
              fProp: 'tancedu'
            }
          }
        ],
        tableData: [
          {
            fangmian: '改善前'
          },
          {
            fangmian: '改善后'
          }
        ]
      }

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

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

相关文章

2023年湖北七大员是哪七大员?七大员考试报名网站是哪里?启程别

2023年湖北七大员是哪七大员&#xff1f;七大员考试报名网站是哪里&#xff1f;启程别 住建厅七大员分类&#xff1a; 施工员&#xff08;土建&#xff0c;装饰装修&#xff0c;设备安装&#xff0c;市政工程&#xff09; 质量员&#xff08;土建&#xff0c;装饰装修&#x…

「从零入门推荐系统」20:推荐系统的未来发展

作者 | gongyouliu 编辑 | gongyouliu 随着科学技术的进步&#xff0c;信息技术、网络技术及物联网的快速发展&#xff0c;新信息的生产与传播更加便捷、快速。特别是最近大火的chatGPT、大模型技术引领的新一轮科技革命&#xff0c;让每一个人都可以轻松地生产各种各样的内容&…

ThreeJS教程:精灵模型Sprite作为标签

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 精灵模型Sprite作为标签 实际开发的时候&#xff0c;可以使用精灵模型Sprite 颜色贴图作为标签&#xff0c;标注三维场景。 下面具体知识点&#xff0c;在精灵模型章节基本都讲解…

【多线程】阻塞队列

1. 认识阻塞队列和消息队列 阻塞队列也是一个队列&#xff0c;也是一个特殊的队列&#xff0c;也遵守先进先出的原则&#xff0c;但是带有特殊的功能。 如果阻塞队列为空&#xff0c;执行出队列操作&#xff0c;就会阻塞等待&#xff0c;阻塞到另一个线程往阻塞队列中添加元素(…

I.MX RT1170启动详解:Boot配置、Bootable image头的组成

文章目录 1 基础知识2 BOOT配置2.1 BOOT_CFG配置2.2 BOOT_MODE 3 Bootable image3.1 文件格式3.2 Bootable image头的组成3.3 Bootable image的生成3.4 例&#xff1a;BootROM之non-XIP加载过程3.5 例&#xff1a;bin文件分析 1 基础知识 &#xff08;1&#xff09;BootROM Bo…

遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型教程

详情点击链接&#xff1a;遥感云大数据在灾害、水体与湿地领域典型案例及GPT模型教程 一&#xff1a;平台及基础开发平台 GEE平台及典型应用案例&#xff1b; GEE开发环境及常用数据资源&#xff1b; ChatGPT、文心一言等GPT模型 JavaScript基础&#xff1b; GEE遥感云重…

什么是homography变换

就是33的可逆矩阵对齐次坐标的变换。也叫射影变换&#xff0c;直射变换。 projectivity projective transformation collineation homography 这几个词在描述齐次坐标下的变换时是同义的。

让IPad变成你的生产力工具?在IPad上用Vscode写代码搞开发

文章目录 前言视频教程1. 本地环境配置2. 内网穿透2.1 安装cpolar内网穿透(支持一键自动安装脚本)2.2 创建HTTP隧道 3. 测试远程访问4. 配置固定二级子域名4.1 保留二级子域名4.2 配置二级子域名 5. 测试使用固定二级子域名远程访问6. iPad通过软件远程vscode6.1 创建TCP隧道 7…

POSTGRESQL 索引添加不合理有什么负面影响

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

软考A计划-试题模拟含答案解析-卷十六

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

基于SpringBoot和vue的若依后台管理系统 部署

RuoYi-Vue是一款前后端分离的极速后台开发框架&#xff0c;基于SpringBoot和Vue。 目录 一、准备 二、启动前端项目 解决报错&#xff1a;digital envelope routines::unsupported 【测试】 三、启动后端项目 四、运行数据库sql文件建表 五、开启redis缓存服务 【redis…

基于html+css的图展示103

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

java 利用poi根据excel模板导出数据(一)

前言 作为B端开发&#xff0c;导出数据是不可以避免的&#xff0c;但是有时候需求很变态&#xff0c;表头复杂的一笔&#xff0c;各种合并单元格&#xff0c;如下图&#xff1a; 这些虽说用代码可以实现&#xff0c;但是很繁琐&#xff0c;而且代码并不能通用&#xff0c;遇到…

哈工大华为提出ControlVideo:一种无需训练的可控视频生成方法

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【扩散模型和Transformer】交流群 导读 哈工大&华为云最新提出了一种可控的文本-视频生成方法ControlVideo&#xff0c;在无需训练的条件下&#xff0c;仅使用一张2080Ti…

长沙之行第二天

这是学习笔记的第 2458篇文章 已经从长沙返京一个多星期了&#xff0c;旅行日记还没有写好&#xff0c;真是羞愧&#xff0c;赶紧补一补回忆。 整体来看返京后这一周我最大的变化就是几乎每天都订1次外卖吃长沙牛肉粉。 第二天 自第一天逛完橘子洲之后&#xff0c;我们的行程重…

3.11 Ext JS文件上传基本使用

文件上传对应的组件是Ext.form.field.File。 组件的效果是输入框+文件选择按钮,如下图所示: 点击“选择文件的按钮”, 会弹出操作系统选择文件的对话框,如下图所示窗口: 选择文件后,输入框会根据不同的浏览器有不同的显示, 有的浏览器是文件名,有的浏览器是完整路径,…

c#特性Attribute

C# 特性&#xff08;Attribute&#xff09; 特性&#xff08;Attribute&#xff09;是用于在运行时传递程序中各种元素&#xff08;比如类、方法、结构、枚举、组件等&#xff09;的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在…

分享几款还不错的工具,这几个工具你们知道吗?

1、可口的披萨 这是一款非常有趣的小游戏&#xff0c;它不仅可以帮助你超解压&#xff0c;还能消磨时间。你将扮演一位店主&#xff0c;经营一家小店。在这个过程中&#xff0c;你会遇到各种不同的人&#xff0c;每个人都有着自己的故事和背景。这些故事非常感人&#xff0c;会…

scitb5函数1.6版本(交互效应函数P for interaction)尝鲜版发布----用于一键生成交互效应表

在SCI文章中&#xff0c;交互效应表格&#xff08;通常是表五&#xff09;几乎是高分SCI必有。因为增加了亚组人群分析&#xff0c;增加了文章的可信度&#xff0c;能为文章锦上添花&#xff0c;增加文章的信服力&#xff0c;还能进行数据挖掘。 在上一个版本中&#xff0c;我们…

使用PlotNeuralNet绘制深度学习网络图的基本操作

使用PlotNeuralNet绘制深度学习网络图的基本操作 PlotNeuralNet工具&#xff0c;具如其名&#xff0c;plot neural net用的&#xff0c;首先我们看看效果&#xff1a; PlotNeuralNet安装与简单命令了解 关于如何安装大家可以参考网上的其他教程&#xff0c;网上有很多教程&…