elementPlus表格组件封装

296 阅读2分钟
  1. 问题:项目中需要用到很多的表格,表格都需要自适应屏幕的高度,如果每次都在一个组件中重新写一样的适应代码就显得很愚蠢。所以对el-table进行了二次封装。
  2. 工具:element-Plus
  3. 表格功能:展开行、多选、分页、触底、高度自适应,剩余功能可继续拓展
  4. 代码实现:
// 封装的table组件
<template>
  <el-table
    ref="tableRef"
    :data="tableData"
    stripe
    :border="border"
    :style="{ width: '100%' }"
    :height="heightAdapt ? tableHeight : null"
    :max-height="maxHeight"
  >
    <!-- 展开行(可选) -->
    <el-table-column v-if="expand" type="expand">
      <template #default="scope">
        <slot name="expand" :row="scope.row" />
      </template>
    </el-table-column>
    <!-- 多选(可选) -->
    <el-table-column v-if="selected" type="selection" width="50" :align="center ? 'center' : ''" />
    <!-- 序号 -->
    <el-table-column type="index" label="序号" width="70" :align="center ? 'center' : ''" />
    <!-- 传值渲染 -->
    <template v-for="(item, index) in (tableController as any[])" :key="index">
      <el-table-column
        v-if="item.visible !== false"
        :prop="item.prop"
        :label="item.label"
        :width="item.width ? item.width : ''"
        :min-width="item.minWidth ? item.minWidth : ''"
        :align="center ? 'center' : ''"
        :fixed="item.fixed ? item.fixed : false"
      >
        <!-- 预留插槽(可选) -->
        <!-- #default="scope" 作用域插槽 使用子组件内部数据 -->
        <template #default="scope" v-if="item.type === 'template'">
          <slot :name="item.prop" :row="scope.row" />
        </template>
      </el-table-column>
    </template>
  </el-table>
  <!-- 分页器 -->
  <el-pagination
    v-if="pager"
    background
    class="table-pagination"
    layout="total, sizes, prev, pager, next, jumper"
    :page-sizes="[20, 50, 100]"
    :page-size="queryParams.pageSize"
    :current-page="queryParams.pageNum"
    :total="total"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />
</template>

<script setup lang="ts">
import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
import { tableHeightResize, tableHeightSelfAdaption } from '@/utils/element-util'

const props = defineProps({
  // 表格数据
  tableData: {
    type: Array,
    default: () => []
  },
  // 表头数据
  tableController: {
    type: Array,
    default: () => []
  },
  // 分页所属--总数据条数
  total: {
    type: Number,
    default: 0
  },
  // 是否加载分页器
  pager: {
    type: Boolean,
    default: true
  },
  border: {
    type: Boolean,
    default: true
  },
  // 是否具有展开行
  expand: {
    type: Boolean,
    default: false
  },
  // 是否加载多选
  selected: {
    type: Boolean,
    default: false
  },
  // 是否内容居中
  center: {
    type: Boolean,
    default: true
  },
  // 是否高度自适应
  heightAdapt: {
    type: Boolean,
    default: true
  },
  // 触底加载
  loadMore: {
    type: Boolean,
    default: false
  },
  // 最大高度
  maxHeight: {
    type: Number,
    default: null
  }
})

// 接收 分页器的分页操作处理函数
const emits = defineEmits(['pagerFresh', 'loadMore'])

// 高度自适应
const tableHeight = ref()
const tableRef = ref()
const setTableHeight = () => {
  tableHeight.value = tableHeightSelfAdaption(tableRef.value)
}
const handleTableResize = () => {
  tableHeight.value = tableHeightResize(tableRef.value) + 8
}
onActivated(() => {
  setTableHeight()
  handleTableResize()
  window.addEventListener('resize', handleTableResize)
})
onDeactivated(() => {
  window.removeEventListener('resize', handleTableResize)
})

// 分页器 默认数据
let queryParams = ref({ pageNum: 1, pageSize: 20 })

// 分页器处理
// 单页数据条数改变
const handleSizeChange = (pageSize: number) => {
  queryParams.value.pageSize = pageSize
  emits('pagerFresh', JSON.parse(JSON.stringify(queryParams.value)))
}
// 页数改变
const handleCurrentChange = (pageNum: number) => {
  queryParams.value.pageNum = pageNum
  emits('pagerFresh', JSON.parse(JSON.stringify(queryParams.value)))
}

// 触底加载
const handleTableScroll = () => {
  const wrapRef = tableRef.value!.$refs.scrollBarRef.wrapRef
  if (!wrapRef) return
  const { scrollHeight, scrollTop, clientHeight } = wrapRef
  if (scrollHeight - clientHeight == scrollTop) {
    //触底
    emits('loadMore')
  }
}

onMounted(() => {
  if (props.loadMore)
    tableRef.value!.$refs.scrollBarRef.wrapRef.addEventListener('scroll', handleTableScroll)
})

onUnmounted(() => {
  if (props.loadMore)
    tableRef.value!.$refs.scrollBarRef.wrapRef.removeEventListener('scroll', handleTableScroll)
})
</script>

<style scoped></style>

自适应高度代码(具体数值根据项目进行调整)

import { ElTable } from 'element-plus'

export const tableHeightSelfAdaption = (
  ref: InstanceType<typeof ElTable> | undefined,
  surplusHeight = 105
) => {
  // 50为padding-top
  return window.innerHeight - ref?.$el.offsetHeight - surplusHeight - 50
}
export const tableHeightResize = (tableRef: InstanceType<typeof ElTable> | undefined) => {
  return window.innerHeight - 60 - tableRef?.$el.offsetTop - 40 - 9 - 5 - 5
}