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