当前位置: 首页 > article >正文

如何在 Vue 中创建一个带有表格和表单的弹窗

本文将通过一个具体的示例来介绍如何在 Vue 应用中实现一个带有表格和表单功能的弹窗组件。我们将使用 Element UI 库中的 el-dialog 组件来构建这个弹窗,并结合 el-table 和 el-form 来展示数据并允许用户进行编辑。

效果图:

完整代码最底部,以下拆分解析----------

1. 引入必要的 Element UI 组件
 

2. 创建弹窗结构
接下来定义弹窗的基本结构。这里我们使用 el-dialog 组件,并为其设置一些基本属性如标题、宽度等:

<el-dialog
  class="edit-dialog"
  title="编辑"
  width="80%"
  :center="true"
  ref="dialogRef"
  :visible.sync="dialogVisible"
  @close="resetForm('resetForm')"
  :before-close="beforeClose"
  :close-on-click-modal="false"
  :close-on-press-escape="false">
</el-dialog>

3. 添加表单和表格
在弹窗内部添加一个表单 (el-form) 和表格 (el-table),并通过 v-model 双向绑定数据

<el-form ref="formRef" style="padding: 20px" label-width="100px">
  <el-table
    border
    stripe
    class="table-style"
    max-height="350"
    :data="tableData"
    style="width: 100%; min-height: 200px;">
    <!-- 表格列定义 -->
  </el-table>
</el-form>

4. 定义表格列
为表格定义多个列,包括索引、发票类型选择器、输入框等:

<el-table-column type="index" label="序号" align="center" width="60" show-overflow-tooltip></el-table-column>
<el-table-column prop="invoiceType" label="发票类型" align="center" min-width="280">
  <template slot-scope="scope">
    <el-select
      multiple
      style="width: 100%"
      collapse-tags
      v-model="scope.row.invoiceTypeCode">
      <el-option
        v-for="(item, index) in typeList"
        :key="index"
        :label="item.invoiceTypeName"
        :value="item.invoiceTypeCode">
      </el-option>
    </el-select>
  </template>
</el-table-column>
<el-table-column prop="taxCategory" label="税收分类简称" align="center" min-width="180">
  <template slot-scope="scope">
    <el-input placeholder="请输入税收分类简称" v-model="scope.row.taxCategory" clearable></el-input>
  </template>
</el-table-column>
<el-table-column prop="taxRate" label="税率" align="center" min-width="180">
  <template slot-scope="scope">
    <el-input placeholder="请输入税率" v-model="scope.row.taxRate" clearable></el-input>
  </template>
</el-table-column>
<el-table-column prop="dateRange" label="适用时间" align="center" min-width="280">
  <template slot-scope="scope">
    <el-date-picker
      v-model="scope.row.dateRange"
      type="daterange"
      range-separator="至"
      value-format="yyyy-MM-dd"
      start-placeholder="开始日期"
      end-placeholder="结束日期">
    </el-date-picker>
  </template>
</el-table-column>
<el-table-column label="操作" align="center" width="80" :render-header="renderHeader">
  <template slot-scope="scope">
    <i @click.prevent="deleteRow(scope.$index, scope.row)" class="el-icon-delete"></i>
  </template>
</el-table-column>

5. 添加操作按钮
在弹窗底部添加两个按钮用于关闭和保存:

<div slot="footer">
  <el-button size="medium" @click="closeDialog">取消</el-button>
  <el-button size="medium" type="primary" ref="saveButton" @click="saveData('formRef')">保存</el-button>
</div>

6. 定义相关方法
最后,在 Vue 实例的方法部分定义与弹窗相关的处理逻辑,例如关闭时重置表单、保存数据等:

export default {
  data() {
    return {
      dialogVisible: false,
      tableData: [],
      typeList: [], // 示例数据
      formRef: null,
      dialogRef: null
    };
  },
  methods: {
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    beforeClose(done) {
      this.resetForm('formRef');
      done();
    },
    deleteRow(index, row) {
      this.tableData.splice(index, 1);
    },
    closeDialog() {
      this.dialogVisible = false;
      this.resetForm('formRef');
    },
    saveData(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          // 保存数据逻辑
          console.log(this.tableData);
          this.closeDialog();
        }
      });
    },
    renderHeader(h, { column }) {
      return h('span', [
        h('i', { style: 'color: #409EFF' }, '添加行'),
        h('span', '操作')
      ]);
    }
  }
};

完整代码如下:

<template>
  <el-dialog
    title="编辑"
    width="80%"
    :center="true"
    ref="dialogRef"
    :visible.sync="dialogVisible"
    @close="resetForm('formRef')"
    :before-close="beforeClose"
    :close-on-click-modal="false"
    :close-on-press-escape="false">
    <el-form ref="formRef" style="padding: 20px" label-width="100px">
      <el-table
        border
        stripe
        class="custom-table"
        max-height="350"
        :data="tableData"
        style="width: 100%; min-height: 200px;">
        <el-table-column type="index" label="序号" align="center" width="60" show-overflow-tooltip></el-table-column>
        <el-table-column prop="invoiceType" label="发票类型" align="center" min-width="280">
          <template slot-scope="scope">
            <el-select
              multiple
              style="width: 100%"
              collapse-tags
              v-model="scope.row.invoiceTypeCode">
              <el-option
                v-for="item in typeList"
                :key="item.invoiceTypeCode"
                :label="item.invoiceTypeName"
                :value="item.invoiceTypeCode">
              </el-option>
            </el-select>
          </template>
        </el-table-column>
        <el-table-column prop="taxCategory" label="税收分类简称" align="center" min-width="180">
          <template slot-scope="scope">
            <el-input
              placeholder="请输入税收分类简称"
              v-model="scope.row.taxCategory"
              clearable>
            </el-input>
          </template>
        </el-table-column>
        <el-table-column prop="taxRate" label="税率" align="center" min-width="180">
          <template slot-scope="scope">
            <el-input
              placeholder="请输入税率"
              v-model="scope.row.taxRate"
              clearable>
            </el-input>
          </template>
        </el-table-column>
        <el-table-column prop="dateRange" label="适用时间" align="center" min-width="280">
          <template slot-scope="scope">
            <el-date-picker
              v-model="scope.row.dateRange"
              type="daterange"
              range-separator="至"
              value-format="yyyy-MM-dd"
              start-placeholder="开始日期"
              end-placeholder="结束日期">
            </el-date-picker>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" width="80" :render-header="renderHeader">
          <template slot-scope="scope">
            <i
              @click.prevent="deleteRow(scope.$index, scope.row)"
              class="el-icon-delete">
            </i>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <div slot="footer">
      <el-button size="medium" @click="closeDialog">取消</el-button>
      <el-button size="medium" type="primary" ref="saveButton" @click="saveData('formRef')">保存</el-button>
    </div>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      dialogVisible: false,
      tableData: [
        {
          invoiceTypeCode: ['1'],
          taxCategory: '',
          taxRate: '',
          dateRange: []
        }
      ],
      typeList: [
        { invoiceTypeCode: '1', invoiceTypeName: '增值税专用发票' },
        { invoiceTypeCode: '2', invoiceTypeName: '增值税普通发票' }
      ]
    };
  },
  methods: {
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    beforeClose(done) {
      this.resetForm('formRef');
      done();
    },
    deleteRow(index, row) {
      this.tableData.splice(index, 1);
    },
    closeDialog() {
      this.dialogVisible = false;
      this.resetForm('formRef');
    },
    saveData(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          console.log(this.tableData);
          this.closeDialog();
        }
      });
    },
    addNewRule() {
      this.tableData.push({
        invoiceTypeCode: [],
        taxCategory: '',
        taxRate: '',
        dateRange: [],
        isDisabled: false
      });
    },
    renderHeader(h, { column }) {
      return h(
        'div',
        [
          h('span', column.label),
          h('i', {
            class: 'el-icon-circle-plus',
            style: 'color: #409eff; font-size: 24px; cursor: pointer;',
            on: {
              click: this.addNewRule
            }
          })
        ]
      );
    }
  }
};
</script>

<style scoped>
.custom-dialog .el-dialog__body {
  padding: 20px;
}

.custom-table {
  margin-bottom: 20px;
}

.custom-table td, .custom-table .cell {
  padding: 0px;
}

.custom-table .el-input__inner {
  border-radius: 0;
}

.custom-table .el-icon-delete {
  cursor: pointer;
}

.custom-dialog .el-dialog__header {
  background: rgb(2, 65, 114);
  color: #fff;

  .el-dialog__title,
  .el-icon {
    color: #fff;
  }
}
</style>


http://www.kler.cn/a/283794.html

相关文章:

  • 【Webpack实用指南】如何拆分CSS资源(2)
  • 除了 Postman,还有什么好用的 API 调试工具吗
  • 机器学习——贝叶斯
  • 「数据要素」行业简报|2024.11.上刊
  • docker运行ActiveMQ-Artemis
  • Typescript类型运算符、关键字以及内置高级类型
  • 数据结构之十字链表
  • 前端篇-html
  • 大数据技术之HBase简介(1)
  • ai免费生成ppt软件有哪些?我推荐秒出PPT
  • 基于detectron2框架的深度学习模型载入自定义数据集
  • 环境变量--永久 & 暂时
  • 设计模式 16 迭代器模式
  • OCI编程高级篇(十四) 直接路径装载设置字段信息
  • 数据结构与算法 第四天(串、数组、广义表)
  • HTTP分析
  • 高级java每日一道面试题-2024年8月30日-数据库篇-数据库的三范式是什么?
  • Java技术栈 —— Spark入门(三)之实时视频流
  • Dubbo如何传递链路追踪id?
  • 小琳AI课堂:使用ChatGPT API搭建系统(二)
  • innovus:如何让部分sink长到target insertion delay的长度
  • 关于OBI 在unity URP环境下使用的正确步骤
  • 网络编程(学习)2024.8.27
  • jQuery基础——选择器的补充方法——过滤方法、查找方法
  • python使用multiprocessing多进程通讯
  • 各种各样的正则表达式