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

vue3封装Element Plus table表格组件

支持绝大部分Element Plus原有设置属性,支持分页,支持动态适配高度

 效果展示

 

组件代码: 
<template>
  <div class="table-wrap" ref="tableWrap">
    <el-table
      class="w100 h100"
      :data="tableInfo.tableData"
      :height="tableHeight"
      v-bind="attrs"
    >
      <!-- 动态生成列 -->
      <template v-for="(item, index) in columns" :key="index">
        <!-- 选择列 -->
        <el-table-column
          v-if="item.type == 'selection'"
          type="selection"
          v-bind="item"
        >
        </el-table-column>

        <!-- 普通列 -->
        <el-table-column v-else-if="!item.subColumns" v-bind="item">
          <template #default="scope">
            <slot :name="item.prop" :scope="scope">
              {{ scope.row[item.prop] }}
            </slot>
          </template>
        </el-table-column>

        <!-- 嵌套列 -->
        <el-table-column v-else v-bind="item">
          <el-table-column
            v-for="(child, childIndex) in item.subColumns"
            :key="childIndex"
            v-bind="child"
          >
            <template #default="scope">
              <slot :name="child.prop" :scope="scope">
                {{ scope.row[child.prop] }}
              </slot>
            </template>
          </el-table-column>
        </el-table-column>
      </template>
    </el-table>
    <el-pagination
      :page-sizes="pageSizes"
      :current-page="page.currentPage"
      :page-size="page.pageSize"
      background
      layout="total, sizes, prev, pager, next, jumper"
      :total="tableInfo.total"
      @size-change="
        handleChangePage({
          currentPage: page.currentPage,
          pageSize: $event,
        })
      "
      @current-change="
        handleChangePage({
          currentPage: $event,
          pageSize: page.pageSize,
        })
      "
    />
  </div>
</template>

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

// Props 接收
const { tableInfo, columns, pageSizes, ...props } = defineProps({
  tableInfo: {
    type: Object,
    default: () => {
      return {
        tableData: [],
        total: 0,
      };
    },
  },
  columns: {
    type: Array,
    default: () => [],
  },
  pageSizes: {
    type: Array,
    default: () => [10, 25, 50, 100],
  },
}); 
const emit =  defineEmits(["current-change"]);
// 获取其他绑定属性
const { attrs } = getCurrentInstance();

// 引用
const tableWrap = ref(null);
const tableHeight = ref(50); // 默认高度
let resizeObserver = null;

//分页
const page = ref({
  currentPage: 1,
  pageSize: 10,
});

//函数
const handleChangePage = ({ currentPage, pageSize }) => {
  page.value.currentPage = currentPage;
  page.value.pageSize = pageSize;
  emit("current-change", { currentPage, pageSize});
};

// 动态计算表格高度
const initResizeObserver = () => {
  if (!tableWrap.value) return;
  //   32是分页高度 10和分页的间隔
  resizeObserver = new ResizeObserver(() => {
    tableHeight.value = tableWrap.value.offsetHeight - 32 - 10 || 500;
  });

  resizeObserver.observe(tableWrap.value);
};

// 生命周期
onMounted(() => initResizeObserver());
onUnmounted(() => resizeObserver?.disconnect());
</script>

<style scoped lang="scss">
.table-wrap {
  width: 100%;
  height: 100%;
  overflow: auto; /* 根据需求适配 */
  display: flex;
  flex-direction: column;
  gap: 10px;
}
</style>
使用方法:

 注意由于表格通过ref="tableWrap"获取的高度,然后ref="tableWrap"设置的高度百分百,所以在使用组件的时候注意组件的外层高度如下方的class="universalTable h100"。

但设置双层表头的时候注意需要把二级表头放在subColumns属性中。

table原生属性可直接加在组件上例如“ :border="true"”的写法,属性方法都可支持

<template>
  <div class="universalTable h100">
    <universalTable
      :border="true"
      :columns="columns"
      :tableInfo="tableInfo"
      ref="refTable"
      @current-change="handleCurrentChange"
    >
      <template #name="{ scope }">
        <span>{{ scope.row.name }}</span>
      </template>
    </universalTable>
  </div>
</template>
<script setup name="Index">
import { ref, reactive, nextTick } from "vue";
//表头数据
const columns = ref([
  {
    type: "selection",
  },
  {
    label: "测试",
    subColumns: [
      {
        prop: "date",
        label: "Date",
        width: 100,
      },
    ],
  },
  {
    prop: "name",
    label: "Name",
    width: 120,
  },
  {
    prop: "address",
    label: "Address",
  },
]);
//列表数据
const tableInfo = ref({
  tableData: [
    {
      date: "2016-05-03",
      name: "Tom",
      address: "No. 189, Grove St, Los Angeles",
    },
    {
      date: "2016-05-02",
      name: "Tom",
      address: "No. 189, Grove St, Los Angeles",
    },
    {
      date: "2016-05-04",
      name: "Tom",
      address: "No. 189, Grove St, Los Angeles",
    },
    {
      date: "2016-05-01",
      name: "Tom",
      address: "No. 189, Grove St, Los Angeles",
    },
  ],
  total: 100,
});
//分页数据
const page = ref({
  currentPage: 1,
  pageSize: 10,
});
//获取分页数据
const handleCurrentChange = ({ currentPage, pageSize }) => {
  page.value.currentPage = currentPage;
  page.value.pageSize = pageSize;
};
</script>

<style scoped lang="scss">
.universalTable {
}
</style>

 


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

相关文章:

  • 【大数据分析机器学习】分布式机器学习
  • 图像增强夜视仪行业全面而深入的分析
  • 游戏陪玩系统开发功能需求分析
  • 循环输出1~100之间的每个数
  • Swift 数组
  • Elasticsearch-Elasticsearch-Rest-Client(三)
  • 网络安全设备系列--安全隔离网闸
  • 代码随想录day44算法随想录|动态规划07
  • B/S架构(笔记整理)
  • 【jvm】StringTable为什么要调整
  • SpringBoot中设置超时30分钟自动删除元素的List和Map
  • 内存、显存和GPU在Transformer架构中承担什么计算任务
  • 【如何用更少的数据作出更好的决策】-gpt生成
  • 华为云容器监控平台
  • 【面试题系列Vue07】Vuex是什么?使用Vuex的好处有哪些?
  • 快速排序-java版本
  • 【开源免费】基于Vue和SpringBoot的私人健身与教练预约管理系统(附论文)
  • WTV芯片在智能电子锁语音留言上的应用方案解析
  • 用Python做一个websocket服务端
  • Nvidia 系列显卡大解析 B100、A40、A100、A800、H100、H800、V100 该如何选择,各自的配置详细与架构详细介绍,分别运用于哪些项目场景
  • VMware如何安装img镜像,VMware如何安装openwrt软路由(含相关工具镜像)
  • OceanBase 中常用的查询语句
  • Linux Xterm字体修改
  • IDEA一键启动多个微服务
  • 汽车资讯新视角:Spring Boot技术革新
  • Android 日常使用整理