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

基于 element-plus 的表格组件二次封装:思路与使用指南

引言

在前端开发中,表格是展示数据的常用组件。Element Plus 提供了强大的表格组件,但在实际项目中,为了提高开发效率和代码的复用性,我们常常需要对其进行二次封装。本文将详细介绍基于 Element Plus 二次封装表格组件的思路,并给出使用说明。源码地址:https://gitcode.com/Jiaberrr/vue3-pc-template/overview,演示地址:https://env-00jxt0stsnl3-static.normal.cloudstatic.cn/index.html

封装思路

组件结构设计

我们的目标是封装一个通用的表格组件,它既包含表格展示部分,又包含分页功能。整体组件结构如下:

  1. 表格部分:使用 el-table 作为基础组件,通过传入不同的属性和插槽来定制表格的外观和内容。
  2. 分页部分:使用 el-pagination 组件,实现分页功能,通过与表格数据的交互,实现数据的分页展示。

属性设计

为了使组件具有通用性,我们设计了一系列属性:

  1. border:控制表格是否有边框,类型为 Boolean,默认值为 true
  2. align:设置表格内容的对齐方式,类型为 String,默认值为 center
  3. tableConfig:这是一个数组,用于配置表格的列信息,是必填项。每个元素包含 label(列名)、width(列宽)、prop(对应数据的属性名)等信息,还可以包含 slot(是否使用插槽)、slotName(插槽名)、formatter(数据格式化函数)等自定义属性。
  4. tableData:表格展示的数据,类型为 Array,默认值为空数组。
  5. selection:控制表格是否显示复选框,用于多选功能,类型为 Boolean,默认值为 false
  6. showIndex:控制表格是否显示序号列,类型为 Boolean,默认值为 true
  7. pagination:控制是否显示分页组件,类型为 Boolean,默认值为 true
  8. pageSize:每页显示的数据条数,类型为 Number,默认值为 10
  9. pageSizes:可供选择的每页数据条数选项,类型为 Array,默认值为 [10, 20, 50, 100]
  10. total:数据的总条数,类型为 Number,默认值为 0

事件处理

组件内部定义了多个事件处理函数,用于与父组件进行交互:

  1. handleSelectionChange:当表格的选择项发生变化时触发,将选中的行数据传递给父组件。
  2. handleEdit:当点击编辑按钮时触发,将当前行的数据传递给父组件,以便进行编辑操作。
  3. handleDelete:当点击删除按钮时触发,将当前行的数据传递给父组件,以便进行删除操作。
  4. handleSizeChange:当用户改变每页显示的数据条数时触发,计算新的查询参数并传递给父组件。
  5. handleCurrentChange:当用户切换到不同的页码时触发,计算新的查询参数并传递给父组件。

自定义序号

为了实现分页情况下序号的正确显示,我们定义了 indexMethod 函数。该函数根据当前页码和每页数据条数,计算出正确的序号。

使用说明

组件页面代码

<template>
  <el-table
    :data="tableData"
    style="width: 100%;"
    :border="border"
    :highlight-current-row="true"
    @selection-change="handleSelectionChange"
  >
    <el-table-column v-if="selection" type="selection" width="55" :align="align" />
    <el-table-column
      v-if="showIndex"
      type="index"
      width="60"
      label="序号"
      :index="indexMethod"
      :align="align"
    />
    <el-table-column
      v-for="(item, index) in tableConfig"
      :key="index"
      :label="item.label"
      :width="item.width"
      :align="align"
    >
      <template #default="scope">
        <slot v-if="item.slot" :name="item.slotName" :row="scope.row">
          <el-button type="primary" plain @click="handleEdit(scope.row)"
            >编辑</el-button
          >
          <el-button type="danger" plain @click="handleDelete(scope.row)"
            >删除</el-button
          >
        </slot>
        <div v-else-if="item.formatter">
          {{ item.formatter(scope.row[item.prop]) }}
        </div>
        <div v-else>{{ scope.row[item.prop] }}</div>
      </template>
    </el-table-column>
  </el-table>
  <el-pagination
    v-if="pagination"
    class="mt-10"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="myPageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
    background
  >
  </el-pagination>
</template>

<script setup>
import { ref } from "vue";

const currentPage = ref(1);
const prop = defineProps({
  border: {
    Type: Boolean,
    default: true,
  },
  align: {
    Type: String,
    default: 'center'
  },
  tableConfig: {
    Type: Array,
    required: true,
  },
  tableData: {
    Type: Array,
    default: () => [],
  },
  selection: {
    Type: Boolean,
    default: false,
  },
  showIndex: {
    Type: Boolean,
    default: true,
  },
  pagination: {
    Type: Boolean,
    default: true,
  },
  pageSize: {
    Type: Number,
    default: 10,
  },
  pageSizes: {
    Type: Array,
    default: () => [10, 20, 50, 100],
  },
  total: {
    Type: Number,
    default: 0,
  },
});

const emit = defineEmits(["updateQueryData", "handleSelectionChange","handleEdit","handleDelete"]);
// 自定义序号
const indexMethod = (index) => {
  return (currentPage.value - 1) * myPageSize.value + index + 1;
};

// 设置每页条数
const myPageSize = ref(prop.pageSize);
const handleSizeChange = (num) => {
  myPageSize.value = num;
  currentPage.value = 1;
  let params = {
    pageNum: (currentPage.value - 1) * myPageSize.value,
    pageSize: myPageSize.value,
  };
  emit("updateQueryData", params, true);
};

// 跳转到该页
const handleCurrentChange = (num) => {
  currentPage.value = num;
  let params = {
    pageNum: (currentPage.value - 1) * myPageSize.value,
    pageSize: myPageSize.value,
  };
  emit("updateQueryData", params, true);
};

const handleSelectionChange = (array) => {
  emit("handleSelectionChange", array);
};

// 编辑
const handleEdit = (row) => {
  emit("handleEdit", row);
};

// 删除
const handleDelete = (row) => {
  emit("handleDelete", row);
};
</script>

<style scoped>
</style>

引入组件

在你的项目中,将封装好的表格组件引入到需要使用的页面中: 

<template>
  <div>
    <MyTable
      :border="true"
      :align="center"
      :tableConfig="tableConfig"
      :tableData="tableData"
      :selection="true"
      :showIndex="true"
      :pagination="true"
      :pageSize="10"
      :pageSizes="[10, 20, 50, 100]"
      :total="total"
      @updateQueryData="updateQueryData"
      @handleSelectionChange="handleSelectionChange"
      @handleEdit="handleEdit"
      @handleDelete="handleDelete"
    />
  </div>
</template>

<script setup>
import MyTable from "@/components/MyTable.vue";
import { ref } from "vue";

const tableConfig = ref([
  { label: "姓名", prop: "name", width: "100" },
  { label: "年龄", prop: "age", width: "80" },
  { label: "操作", slot: true, slotName: "operation", width: "120" }
]);

const tableData = ref([
  { name: "张三", age: 20 },
  { name: "李四", age: 25 },
  { name: "王五", age: 30 }
]);

const total = ref(3);

const updateQueryData = (params, isReset) => {
  // 根据参数重新请求数据
};

const handleSelectionChange = (array) => {
  console.log("选中的行数据:", array);
};

const handleEdit = (row) => {
  console.log("编辑行数据:", row);
};

const handleDelete = (row) => {
  console.log("删除行数据:", row);
};
</script>

<style scoped>
</style>

配置表格列

通过 tableConfig 属性配置表格的列信息。每个元素可以包含以下属性:

  • label:列名,用于显示在表格头部。
  • prop:对应数据的属性名,用于从 tableData 中获取数据。
  • width:列宽,设置表格列的宽度。
  • slot:是否使用插槽,若为 true,则会在该列中渲染自定义插槽内容。
  • slotName:插槽名,用于在父组件中定义插槽内容。
  • formatter:数据格式化函数,用于对表格数据进行格式化处理。

数据传递

通过 tableData 属性传递表格展示的数据,通过 total 属性传递数据的总条数。

事件处理

父组件可以通过监听 updateQueryDatahandleSelectionChangehandleEdithandleDelete 等事件,来处理分页、选择、编辑、删除等操作。

总结

通过对 Element Plus 表格组件的二次封装,我们实现了一个通用的表格组件,提高了代码的复用性和开发效率。在实际项目中,可以根据具体需求进一步扩展和优化该组件。希望本文对你有所帮助,如有任何问题,欢迎在评论区留言。


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

相关文章:

  • JavaScript性能
  • 【重庆】《政务数字化应用费用测算规范》(T/CDCIDA 001—2023)-省市费用标准解读系列36
  • 二、CSS基础
  • JAVA:利用 Redis 实现每周热评的技术指南
  • 等保测评和密评的相关性和区别
  • 4.Web安全——JavaScript基础
  • HTML——52.布局淘宝网
  • DVWA靶场Brute Force (暴力破解) 漏洞low(低),medium(中等),high(高),impossible(不可能的)所有级别通关教程
  • LeetCode算法题——螺旋矩阵ll
  • 35.回车触发事件 C#例子 WPF例子
  • 可由 (5V) 单片机直接驱动的模块
  • Datawhale AI冬令营(第二期)动手学AI Agent--Task3:学Agent工作流搭建,创作进阶Agent
  • 访谈分析方法
  • DRAM 的类型
  • 【大模型系列】Mobile-Agent(2024.04)
  • 【Devops】什么是Devops?(Development+Operations)和运维的区别?
  • Java-多种方法实现多线程计数
  • 常见的 Redis 面试题
  • flux中的缓存
  • 《Vue3实战教程》43:Vue3TypeScript 与选项式 API
  • Java之图书管理系统
  • 单周期CPU电路设计
  • Vue.js 表单验证实战:一个简单的登录页面
  • idea最强ai辅助工具豆包的使用教程
  • 观成科技:伪猎者(APT-C-60)APT组织加密通信分析
  • 港科大开源VideoVAE+,视频重建质量全面超越最新模型