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

news2024/9/22 21:37:32

基于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>

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

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

相关文章

微信小程序:flex常用布局

在我们平时微信小程序开发过程中为了页面能达到设计小伙伴的预期&#xff0c;追求还原度&#xff0c;那我们肯定会使用很多常用的布局方式&#xff0c;那我们今天就介绍一下微信小程序中常用的一些flex布局 1、常用flex布局 /** 水平垂直居中 **/ .flex-center {display: fle…

鸿鹄电子招投标系统源码实现与立项流程:基于Spring Boot、Mybatis、Redis和Layui的企业电子招采平台

随着企业的快速发展&#xff0c;招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求&#xff0c;建立一个公平、公开、公正的采购环境至关重要。在这个背景下&#xff0c;我们开发了一款电子招标采购软件&#xff0c;以最大限度地控制采购成本&#…

普中STM32-PZ6806L开发板(HAL库函数实现-温度传感器DS18B20)

简介 主芯片STM32F103ZET6, 通过引脚PG11 连接DS18B20, 读取DS18B20采集的温度数据;电路原理图 DS18B20电路图 DS18B20 与 主芯片连接引脚 其他知识 DS18B20资料 DS18B20数据手册 DS18B20 简介 单线通讯的温度传感器, 测量温度在-55℃ 到 125℃&#xff0c; 在-10C 到…

[大厂实践] 重新发明后端子集

子集算法有助于优化服务间连接利用率&#xff0c;降低资源使用。但随机或轮询子集算法在动态拓扑环境中会造成较高的连接扰动。本文介绍了谷歌在解决连接扰动方面所做的思考和实践&#xff0c;并介绍了当前最新的Rocksteadier子集算法。原文: Reinventing Backend Subsetting a…

算法的复杂度分析

[王有志](https://www.yuque.com/wangyouzhi-u3woi/dfhnl0/hqrch62un0cc9sp2?singleDoc# 《&#x1f525;快来关注我》)&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;[共同富裕的Java人](https://www.yuque.com/wangyouzhi-u3woi/dfhnl0/n…

pytorch集智-2单车预测器

完整代码在个人主页简介链接pytorch路径下可找到 1 单车预测器1.0 1.1 人工神经元 对于sigmoid函数来说&#xff0c;w控制函数曲线的方向&#xff0c;b控制曲线水平方向位移&#xff0c;w控制曲线在y方向的幅度 1.2 多个人工神经元 模型如下 数学上可证&#xff0c;有限神经…

前端ui库搜集

涟漪动画效果 - MDUI 开发文档, Material Design 前端框架添加涟漪动画效果后&#xff0c;会在点击元素时&#xff0c;产生向外扩散的水波纹效果。https://www.mdui.org/docs/ripple#ripple https://semantic-ui.com/ https://getuikit.com/ https://www.purecss.cn/grids.htm…

iview table 表格合并行鼠标悬停时的高亮

背景&#xff1a; Iview里面的表格没有提供鼠标移入移出的事件。 而且当开启鼠标悬浮高亮的时候会显示异常&#xff0c;并没有高亮合并后的整行&#xff0c;还是高亮子行。 高亮前&#xff1a; 高亮异常情况&#xff1a; 解决后&#xff1a; 解决方案&#xff1a; 一、思路&…

第6章 密码学和对称密钥算法

6.1 密码学基本知识 6.1.1 密码学的目标 安全从业者可借助密码系统实现4个基本目标&#xff1a;保密性、完整性、身份认证和不可否认性。 其中每个目标的实现都需要满足诸多设计要求&#xff0c;而且并非所有密码系统都是为达到所有4个目标而设计的。 下面的小节将详细讲解这…

我的剑,传给能挥舞它的人--量化书籍推荐!

这篇笔记介绍量化入门的参考书目。 前1/4叹为观止&#xff0c;再1/4勉强点赞&#xff0c;再1/4乏善可陈&#xff0c;最后1/4简直不忍卒读。这是我对某本名书的评价&#xff0c;希望你并不会将这句话还给我。“不会的”&#xff0c;我安慰自己。不是文章多好&#xff0c;但你们…

云卷云舒:【实战篇】对象存储迁移

云卷云舒&#xff1a;【实战篇】MySQL迁移-CSDN博客 1. 简介 对象存储与块存储、文件存储并列为云计算三大存储模型。提供海量存储空间服务&#xff0c;具备快速的数据存取性能、高可靠和数据安全性&#xff0c;通过标准的RESTful API接口和丰富的SDK包来提供服务&#xff0c…

基于SSM的校内信息服务发布系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

uniapp 微信小程序跳转至其他小程序

一、背景&#xff1a; 需要在目前的小程序中跳转到另一个小程序&#xff0c;跳转的目标小程序需要已经发布上线了 二、具体实现 使用uni.navigateToMiniProgram打开另一个小程序 官网指引&#x1f449;&#xff1a;uni.navigateToMiniProgram(OBJECT) | uni-app官网 <t…

RA8900CE汽车用c总线接口实时时钟模块

汽车用c总线接口实时时钟模块内置调频32.768 kHz晶体单元和DTCXO&#xff0c;高稳定性和电源切换。 接口类型我 2C-Bus接口(400kHz)界面电压范围2.5V ~ 5.5V温度补偿电压范围2.0V至5.5V计时电压范围1.6V ~ 5.5V可选时钟输出(32.768 kHz, 1024 Hz, 1 Hz)各种功能齐全的日历、报…

css3 transform:scale

transform:scale 语法&#xff1a;transform:scale(x,y); <html> <head><style>.box1 {display: inline-block;width: 200px;height: 200px;background-color: pink;}.box2 {display: inline-block;width: 200px;height: 200px;background-color: red;tran…

第85讲:MySQLDump与Binlog日志实现企业级数据备份恢复案例

文章目录 1.企业级数据备份恢复案例描述2.第一环节&#xff1a;周三凌晨进行数据全量备份3.第二环节&#xff1a;模拟周三凌晨备份完之后到下午3点前的业务操作4.第三环节&#xff1a;模拟数据库异常数据丢失导致平台无法使用5.第四环节&#xff1a;发布停服公告全员进入数据恢…

计算机组成原理 I/O方式

I/O 方式 I/O方式分类: 程序查询方式。由 CPU通过程序不断查询 /O 设备是否已做好准备&#xff0c;从而控制0 设备与主机交换信息程序中断方式。只在 I/0 设备准备就绪并向 CPU发出中断请求时才予以响应。DMA方式。主存和 I/O 设备之间有一条直接数据通路&#xff0c;当主存和…

什么是IT安全(Information Technology Security)?它的价值如何体现

文章目录 一、IT安全名词解释二、IT安全面临的威胁三、IT安全的类型3.1 网络安全3.2 系统安全3.3 应用安全3.4 数据安全3.5 用户安全3.6 物理安全3.7 安全管理 四、IT 安全和信息安全 ( InfoSec )之间有什么区别&#xff1f;IT安全信息安全&#xff08;InfoSec&#xff09; 五、…

湖南大学-计算机网路-2023期末考试【部分原题回忆】

前言 计算机网络第一门考&#xff0c;而且没考好&#xff0c;回忆起来的原题不多。 这门学科学的最认真&#xff0c;复习的最久&#xff0c;考的最差。 教材使用这本书&#xff1a; 简答题&#xff08;6*530分&#xff09; MTU和MSS分别是什么&#xff0c;联系是什么&#x…

内外网文件交换系统实用技巧揭秘:安全、效率、便捷一个不少

内外网文件交换系统是一种专门设计用于在企业内部网络&#xff08;内网&#xff09;与外部网络&#xff08;外网&#xff09;之间安全传输文件的技术解决方案。在企业环境中&#xff0c;出于安全考虑&#xff0c;内部网络通常与外部网络隔离&#xff0c;以防止未经授权的访问和…