Demo:基于elementplus的弹窗嵌套表单进行二次封装

基于elementplus的弹窗嵌套表单进行二次封装

所见即所得:简单封装方便工作
在这里插入图片描述
在这里插入图片描述

ProForm.vue代码:

<!--
 * @Author: 忆往昔
 * @LastEditTime: 2024-01-6 14:36:00
 * @email: 15871856064@163.com
-->
<template>
  <div class="penk-form-container">
    <el-dialog
      v-model="visible1"
      :fullscreen="props.fullscreen"
      :draggable="props.draggable"
      :title="props.title"
      :width="props.width || '50%'"
    >
      <el-form
        ref="ruleFormRef"
        label-width="120px"
        size="large"
        :model="form"
        :rules="props.formConfig.rules"
      >
        <template v-for="item in props.formConfig.formItemConfig" :key="item.prop">
          <el-form-item
            :label="item.label + ':'"
            :style="{ display: item.hidden == true ? 'none' : '' }"
            :prop="item.prop"
          >
            <!-- 输入框 -->
            <el-input
              v-if="item.type == 'input'"
              v-model="form[item.prop]"
              :placeholder="item.placeholder || ''"
              :clearable="item.clearable"
              :disabled="item.disabled"
              :type="item.inputType"
              :row="item.row"
              :style="{ width: item.width + 'px' }"
            />

            <!-- 下拉框 -->
            <el-select
              v-else-if="item.type == 'select'"
              v-model="form[item.prop]"
              :placeholder="item.placeholder"
              :clearable="item.clearable"
              :disabled="item.disabled"
              :style="{ width: item.width + 'px' }"
            >
              <el-option
                v-for="option in item.data"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>

            <!-- 多选框 -->
            <el-checkbox-group
              v-else-if="item.type == 'checkbox'"
              v-model="form[item.prop]"
              :placeholder="item.placeholder"
              :clearable="item.clearable"
              :disabled="item.disabled"
              :style="{ width: item.width + 'px' }"
            >
              <el-checkbox
                v-for="option in item.data"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
                >{{ option.label }}</el-checkbox
              >
            </el-checkbox-group>

            <!-- 单选框 -->
            <el-radio-group
              v-else-if="item.type == 'radio'"
              v-model="form[item.prop]"
              :placeholder="item.placeholder"
              :clearable="item.clearable"
              :disabled="item.disabled"
              :style="{ width: item.width + 'px' }"
            >
              <el-radio
                :label="option.value"
                size="large"
                v-for="option in item.data"
                :key="option.label"
                >{{ option.label }}</el-radio
              >
            </el-radio-group>
          </el-form-item>
        </template>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="visible1 = false">取消</el-button>
          <el-button type="primary" @click="confirm(ruleFormRef)"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, watch, defineEmits, onMounted } from 'vue'
import { ElMessage } from 'element-plus'

let form = reactive({})
const visible1 = ref(true)
const ruleFormRef = ref()

const props = defineProps({
  formData: {
    type: Object,
    default: () => {}
  },
  formConfig: {
    type: Object,
    default: () => {}
  },
  visible: {
    type: Boolean,
    default: false
  },
  width: {
    type: String,
    default: '520px'
  },
  title: {
    type: String,
    default: '新增'
  },
  fullscreen: {
    type: Boolean,
    default: false
  },
  draggable: {
    type: Boolean,
    default: false
  },
  'append-to-body': {
    type: Boolean,
    default: false
  },
  'close-on-click-modal': {
    type: Boolean,
    default: false
  }
})

// 生成事件对象,数组中就是对象名
const emit = defineEmits(['update:visible', 'confirm'])

// 监听父组件的visible,用来简介控制el-dialog的弹框开关,一般是用于开
watch(
  () => props.visible,
  (n, o) => {
    visible1.value = n
  }
)
// 监听el-dialog显示状态,再通过@update:visible 通知父组件,一般是用于关
watch(visible1, (n, o) => {
  emit('update:visible', n)
})

// 每次触发,就证明父组件点了修改或者添加的按钮,传递了一个新的formData
// 需要重新给form 赋值,并且,对该表单项进行重置
watch(
  () => props.formData,
  (n, o) => {
    resetForm(ruleFormRef.value)
    form = reactive(n)
  }
)

// 确定按钮触发
const confirm = async (formEl) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      emit('confirm', form)
    } else {
      console.log('error submit!', fields)
      ElMessage({
        showClose: true,
        message: '请完善表单信息!',
        type: 'error'
      })
    }
  })
}

// 重置表单
const resetForm = (formEl) => {
  if (!formEl) return
  formEl.resetFields()
}

onMounted(() => {
  console.log(props.formConfig);
  // 初始化 配置弹框是否可显示
  visible1.value = props.visible
  // 初始化 配置formData
  props.formConfig.formItemConfig.map((item) => {
    form[item.prop] = ''
  })
})
</script>

<style lang="scss" scoped>
.penk-form-container {
  .el-table-border {
    border: 1px #eee solid;
  }
  :deep(.el-dialog__body) {
    border-top: 1px solid #eee;
  }
}
</style>
组件使用示例:
<template>
  <MyTable
    :tableData="tableData"
    :columns="columns"
    :total="total"
    :currentPage="listQuery.pageNo"
    :pageSize="listQuery.pageSize"
    @changeTableData="changeTableData"
  >
    <!-- <template #check="{ slotProps }">
      <el-tag class="ml-2" :type="slotProps.check ? 'success' : 'danger'">
        {{ checkFilter(slotProps.check) }}
      </el-tag>
    </template> -->
    <template #operator="{ slotProps }">
      <el-button type="primary" @click="setData('edit', slotProps)">编辑</el-button>
      <el-button type="primary" @click="handleAddItem">新增</el-button>
      <el-button type="primary" @click="handleEditItem(slotProps)">修改</el-button>
      <el-button type="danger" @click="handleDel(slotProps)">删除</el-button>
    </template>
  </MyTable>
  <!-- 表单弹框 -->
  <ProForm
    :title="title"
    :formConfig="formConfig"
    :formData="formData"
    v-model:visible="visible"
    append-to-body
    @confirm="saveItem"
  />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import MyTable from '@/components/MyTable/MyTable.vue'
import ProForm from '@/components/ProForm/ProForm.vue'

let listQuery = ref({
  pageNo: 1,
  pageSize: 10
})
const tableData = ref([
  { number: '001', numberplate: '京A12345', date: '2022-01-01', check: '正常', operator: '编辑' },
  { number: '002', numberplate: '京B67890', date: '2022-02-01', check: '正常', operator: '编辑' },
  { number: '003', numberplate: '京C24680', date: '2022-03-01', check: '故障', operator: '编辑' },
  { number: '004', numberplate: '京D13579', date: '2022-04-01', check: '正常', operator: '编辑' },
  { number: '005', numberplate: '京E97531', date: '2022-05-01', check: '正常', operator: '编辑' }
])
let total = ref(0)

/**
 * prop:数据项列名
 * label:列名展示名
 * fixed:固定列 true/right/left
 * width:列宽
 * show-overflow-tooltip
 * type:对应列的类型 selection / index / expand
 * sortable:true/false
 * selectable:Function
 * formatter:格式化内容 function(row, column, cellValue, index)
 **/
let columns = ref([
  { prop: 'number', label: '车牌自编号' },
  { prop: 'numberplate', label: '车牌号' },
  { prop: 'date', label: '出厂日期' },
  { prop: 'check', label: '车辆状态' },
  { prop: 'operator', label: '操作', fixed: 'right' }
])

onMounted(() => {})

const changeTableData = (pageNum, pageSize) => {
  listQuery.value.pageNo = pageNum
  listQuery.value.pageSize = pageSize
  getCarList()
}

const visible = ref(false) // 控制弹窗开关
const title = ref('') // 弹窗标题
const formData = ref({}) // 表单数据

// 表单配置项
const formConfig = {
  formItemConfig: [
    {
      label: '类型名',
      prop: 'typeName',
      type: 'input'
    },
    {
      label: '父级类型名',
      prop: 'parentId',
      type: 'select',
      data: []
    }
  ],
  rules: {
    typeName: [
      {
        required: true,
        message: '请输入类型名',
        trigger: 'blur'
      }
    ]
  }
}

// 添加数据按钮
const handleAddItem = () => {
  visible.value = true
  title.value = '新增'
  formData.value = {}
}

// 修改数据按钮
const handleEditItem = (row) => {
  visible.value = true
  title.value = '修改'
  formData.value = row
}

// 表单提交
const saveItem = (form) => {
  console.log('提交', form)
}
</script>

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

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

相关文章

【SpringBoot实战专题】「开发实战系列」全方位攻克你的技术盲区之Spring定义Jackson转换Null的方法和实现案例

Spring自动定义Jackson转换Null得方法 背景MessageConverter 使用Jackson原生方式处理空字段&#xff08;次重点方案&#xff09;ObjectMapper的配置选项通过使用注解的方式 MappingJackson2HttpMessageConverter&#xff08;重点方案&#xff09;创建MappingJackson2HttpMessa…

WebStorm 创建一个Vue项目

一、下载并安装WebStorm 步骤一 步骤二 选择激活方式 激活码&#xff1a; I2A0QUY8VU-eyJsaWNlbnNlSWQiOiJJMkEwUVVZOFZVIiwibGljZW5zZWVOYW1lIjoiVU5JVkVSU0lEQURFIEVTVEFEVUFMIERFIENBTVBJTkFTIiwiYXNzaWduZWVOYW1lIjoiVGFvYmFv77yaSkVU5YWo5a625qG25rAIOa0uW3peS9nOWup…

Easycode模板,基于官方提供的Mybatis-plus模板改造

目录结构 模板亮点 1、接口类默认继承实体类 实体类不做任何修改保证类与表统一 2、实体类涵盖多种注解 日期格式编码、Long类型转String、字段自动填充 3、自带insertOrUpdateBatch方法 导入方式 {"author" : "Wsong","version" : "1.2.8…

SpringBoot+RocketMQ集群(dledger)部署完整学习笔记

文章目录 前言一、单台集群部署二、多台集群部署1.修改配置2.dashboard修改 三、整合springboot1.引入pom和修改yml2.编写消费者3.编写生产者4.测试效果 总结 前言 RocketMQ集群方式有好几种 官网地址 https://rocketmq.apache.org/zh/docs/4.x/deployment/01deploy 2m-2s-asy…

ATTCK视角下的信息收集:主机发现

目录 1、利用协议主动探测主机存活 利用ICMP发现主机 利用ARP发现主机 利用NetBIOS协议发现主机 利用TCP/UDP发现主机 利用DNS协议发现主机 利用PRC协议发现主机程序 2、被动主机存活检测 利用Browser主机探测存活主机 利用ip段探测主机存活 利用net命令探测主机存活…

unity C# 中通俗易懂LINQ使用案例

文章目录 1. 从数组或列表中查询元素**&#xff1a;2. **排序与分组**&#xff1a;3. **连接多个数据源**&#xff1a;4. **聚合操作**&#xff1a;5. **分页查询**&#xff1a;6. **多条件查询**&#xff1a;7. **转换和投影&#xff08;Select&#xff09;**&#xff1a;8. *…

jdbc源码研究

JDBC介绍 JDBC&#xff08;Java Data Base Connectivity,java数据库连接&#xff09;是一种用于执行SQL语句的Java API&#xff0c;可以为多种关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。 开发者不必为每家数据通信协议的不同而疲于奔命&#…

竞赛保研 基于深度学习的人脸专注度检测计算系统 - opencv python cnn

文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的人脸专注度…

Flask 会员列表展示

感谢编程浪子师傅的源码信息分享 web/controllers/member/Member.py # -*- coding: utf-8 -*- from flask import Blueprint,request,redirect,jsonify from common.libs.Helper import ops_render,iPagination,getCurrentDate,getDictFilterField,selectFilterObj from comm…

【uniapp】APP打包上架应用商-注意事项

初雪云-uniapp启动图自定义生成&#xff08;支持一键生成storyboard&#xff09; 一、修改App端上传图片/视频 uni.uploadFile let thatthis; uni.chooseImage({count: 1,sourceType: [camera,album],sizeType: [compressed, original],success: rey > {uni.showLoading({ t…

Linux操作系统——进程控制(一) 进程创建和进程终止

进程创建 fork函数 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 #include <unistd.h> pid_t fork(void); 返回值&#xff1a;自进程中返回0&#xff0c;父进程返回子进程id&#xff…

BetaFlight开源代码之电流校准

BetaFlight开源代码之电流校准 1. 源由2. 分析2.1 常规逻辑2.2 数据流2.3 采样电路2.3.1 采样实现2.3.2 采样原理2.3.3 Layout参考2.3.4 INA169芯片2.3.5 INA169 Near-Zero Vsense 3. 原理4. 示例4.1 实测&转换数据4.2 线性拟合-小电流4.3 线性拟合-大电流4.4 大电流/小电流…

HDMI彩条显示实验与方块移动实验

一、HDMI接口简介 一种数字音视频接口标准&#xff0c;提供高质量的数字音视频传输&#xff0c;同时支持多通道音频、高分辨率视频和其他数据传输功能。提供更高的数据传输带宽&#xff08;带宽&#xff1a;1s内传输多少比特数据&#xff09; 数字传输&#xff1a; HDMI是一种全…

【VRTK】启用多种VR设备的Passthrough功能

【背景】 透视可以让VR头盔展现AR能力,通过VRTK,可以快速实现多种设备平台可用的透视功能。包括主流的Oculus,Pico等。整个不成不需要自己写代码。 【操作】 针对WaveXR,点击场景中的CameraRigsWaveXR-》WaveRig-》Camera Offset-》Main Camera,追加一个新组件,名为Und…

QT自定义信号和槽

信号和槽 介绍实现创建文件对teacher的h和cpp文件进行处理对student的h和cpp文件进行处理对widget的h和cpp文件进行处理 介绍 Qt中的信号和槽是一种强大的机制&#xff0c;用于处理对象之间的通信。它们是Qt框架中实现事件驱动编程的核心部分。 信号&#xff08;Signal&#x…

vite4项目中,vant兼容750适配

一般非vite项目&#xff0c;使用postcss-px-to-viewport。在设计稿为750时候&#xff0c;可使用以下配置兼容vant。 在vite4项目中&#xff0c;以上配置不行。需要调整下&#xff0c;使用postcss-px-to-viewport-8-plugin&#xff0c;并修改viewportWidth&#xff0c;具体如下…

51单片机定时/计数器相关知识点

51单片机定时/计数器相关知识点 结构组成 51单片机的定时/计数器中有两个寄存器&#xff1a; T0&#xff1a;低位&#xff1a;TL0&#xff08;字节地址8AH&#xff09;高位&#xff1a;TH0&#xff08;字节地址8CH&#xff09;T1&#xff1a;低位&#xff1a;TL1&#xff08…

走向云原生 破局数字化

近年来&#xff0c;随着云计算概念和技术的普及&#xff0c;云原生一词也越来越热门&#xff0c;云原生成为云计算领域的新变量。行业内&#xff0c;华为、阿里巴巴、字节跳动等各个大厂都在“抢滩”云原生市场。行业外&#xff0c;云原生也逐渐出圈&#xff0c;出现在大众视野…

Visual Studio Code安装C#开发工具包并编写ASP.NET Core Web应用

前言 前段时间微软发布了适用于VS Code的C#开发工具包&#xff08;注意目前该包还属于预发布状态但是可以正常使用&#xff09;&#xff0c;因为之前看过网上的一些使用VS Code搭建.NET Core环境的教程看着还挺复杂的就一直没有尝试使用VS Code来编写.NET Core。不过听说C# 开发…

设计模式Java实战,彻底学会

​这是全网最强的Java设计模式实战教程。此教程用实际项目场景&#xff0c;结合SpringBoot&#xff0c;让你真正掌握设计模式。 网址是&#xff1a;Java设计模式实战专栏介绍 - 自学精灵&#xff08;也可以百度搜索“自学精灵”&#xff09;。 本设计模式专栏的威力 用Java实…