封装el-table并实现前端动态显隐列及操作列宽度自适应

桃一一一一 2024-07-06 12:33:01 阅读 71

项目场景:

在管理系统中,前端多用表格展示数据,而有些时候数据列会比较多,对于某些用户来说,有些数据列不必关注,则需要可以根据自己想要看的数据来改变表头列显示哪些隐藏哪些

我elementPlus用得多,因此便想对el-table进行简单封装,实现前端动态显隐列及操作列宽度自适应

在写前也参考过很多人的代码,但是很多都要额外传递参数,或者将数据组建成特定格式,很不方便;因此我此次封装希望少进行一些额外配置,力图还原el-table的用法

写得不好的地方多多见谅…


实现效果:

<code>提示:先上个效果图,要是不符合大家想要的效果,可以及时看下一篇:

GIF图:

在这里插入图片描述


代码:

提示:下面是具体代码:

(1)组件代码

<code><template>

<el-table ref="tableRef" v-bind="$attrs" :key="Math.random()">code>

<template v-for="(item) in slotList">code>

<component

v-if="item.props != null && initialColumnList.some((col) => { return item.props.label == col.label && col.isShow == true })"code>

:is="item">code>

</component>

</template>

<el-table-column align="center" label="操作" fixed="right" :width="operateColumnWidth">code>

<template #header>

<el-popover placement="bottom" popper-class="column-popover" :width="200" trigger="hover">code>

<template #reference>

<span>

操作

<el-icon>

<ArrowDownBold />

</el-icon>

</span>

</template>

<el-checkbox class="column-checkgroup-item" v-model="showAllColumnFlag"code>

:indeterminate="isIndeterminate" @change="handleCheckAllChange">全选</el-checkbox>code>

<el-divider />

<el-checkbox class="column-checkgroup-item" v-for="(item) in initialColumnList"code>

v-model="item.isShow" :label="item.label" :key="item.label" :disabled="item.label == '操作'" />code>

</el-popover>

</template>

<template #default="scope">code>

<div ref="operateItemGroup">code>

<slot name="operate" :scope="scope" />code>

</div>

</template>

</el-table-column>

</el-table>

</template>

<script setup lang="ts">code>

import { RendererElement } from 'vue'

import { ElTable } from 'element-plus';

const slots = useSlots()

const slotList = ref<RendererElement[]>([]) // 所有列,甚至包含注释

const initialColumnList = ref([]) // 正常列,排除注释内容

const showAllColumnFlag = ref(true);

const tableRef = ref<InstanceType<typeof ElTable>>()

const operateItemGroup = ref()

const emits = defineEmits(["getTableRef"]);

// 用于多选

const getTableRef = () => {

emits('getTableRef', tableRef.value)

}

// 操作列宽度

const operateColumnWidth = ref(0)

// 动态设置操作列宽

watch(

() => operateItemGroup.value,

() => {

if (operateItemGroup.value) {

if(operateItemGroup.value.children.length==0){

// 设置为0,el-table-column会自己设置一个默认宽度

// 设置为1,目前会造成操作列基本不显示,即由于操作列处有可以选择哪些列不显示

// 操作列不显示后,即没办法选择哪些列不显示

operateColumnWidth.value = 1;

}else{

operateColumnWidth.value = operateItemGroup.value.children.length * 90;

}

}

}

)

onMounted(() => {

getTableRef();

initSlotList();

})

// 初始化所有列

const initSlotList = () => {

if (slots.default) { // el-table-column 使用时不传name 所以属于默认插槽

slotList.value = slots.default() || [] // 语法

initDynamicColumn() // 初始化动态列

}

}

// 初始化动态列

const initDynamicColumn = () => {

slotList.value.map(item => {

const colProps = item.props

// 存label,即表头名称,不存prop属性是因为,有些列使用插槽无需使用prop属性

if (colProps != null && typeof colProps === 'object' && colProps.label) {

initialColumnList.value.push({ label: colProps.label, isShow: true })

}

})

initialColumnList.value.push({ label: "操作", isShow: true })

}

// 列选中与半选的状态控制, 条件就是 当前选中的数据个数大于0 且 小于所有列的总数

const isIndeterminate = computed<boolean>(() => {

const showColumnArray = initialColumnList.value.filter((item) => {

return item.isShow == true

});

return showColumnArray.length > 0 && showColumnArray.length < initialColumnList.value.length

})

// 列全选与否的事件控制器

const handleCheckAllChange = (boolean: any) => {

if (boolean) { // 全选

for (let i = 0; i < initialColumnList.value.length; i++) {

initialColumnList.value[i].isShow = true;

}

} else { // 全不选

for (let i = 0; i < initialColumnList.value.length; i++) {

if (initialColumnList.value[i].label != "操作") {

initialColumnList.value[i].isShow = false;

}

}

}

}

</script>

<style scoped lang="scss">code>

</style>

(2)父组件使用参考

<BPTable :data="firstTableData" border stripe highlight-current-row>code>

<el-table-column type="index" label="序号" align="center" width="50" />code>

<el-table-column property="name" align="center" label="菜单名称" />code>

<el-table-column prop="remark" align="center" label="权限备注" />code>

<!-- 操作列 -->

<template #operate="obj">code>

<el-button v-perms="['sys:menu:update']" text icon="Edit" type="primary"code>

@click="openUpdateDialog(obj.scope.row)">code>

修改

</el-button>

<el-button v-perms="['sys:menu:delete']" text icon="Delete" type="danger"code>

@click="openDeleteDialog(obj.scope.row.id)">code>

删除

</el-button>

</template>

</BPTable>




声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。