- 问题:项目中需要用到很多的表格,表格都需要自适应屏幕的高度,如果每次都在一个组件中重新写一样的适应代码就显得很愚蠢。所以对el-table进行了二次封装。
- 工具:element-Plus
- 表格功能:展开行、多选、分页、触底、高度自适应,剩余功能可继续拓展
- 代码实现:
// 封装的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
}