vue3 el-table控制列显示隐藏
TableControl.vue
<!-- 表格列显示隐藏控制 *** 根节点为el-table,会穿透接收组件所有属性 1、通过slots接收表格列,生成勾选项 2、从缓存中读取数据,匹配勾选项; 3、双向绑定,勾选项。表格列使用v-if判断显示隐藏; --> <template> <el-table> <template v-for="(item, index) in slotList" :key="index"> <component v-if="onShowColumn(item)" :is="item" :column-key="item.columnKey"></component> </template> </el-table> </template> <script setup lang="ts"> const slots = useSlots(); // 表格列 const fields = defineModel('fields', { type: Array, default: [] }); const slotList = ref<any[]>([]); /** * 初始化勾选列表 */ const initSlotList = () => { if (slots.default) { // el-table-column 使用时不传name 所以属于默认插槽 const _slotList = slots.default() || []; _slotList.forEach((d: any, index: number) => { // 生成列的key d.columnKey = d.props ? d.props.label : window.btoa(index.toString()); // 生成列的prop if (d.props) { d.props.prop = d.props.prop ? d.props.prop : d.props.label; } }); fields.value = _slotList // 注释代码也会被当节点读取进来 .filter((d: any) => d && d.props) .map((d: any) => { return { label: d.props.label, propName: d.props.prop, checked: true, }; }); slotList.value = _slotList; } }; function onShowColumn(col: any) { if (col && !col.props) { return true; } const field: any = fields.value.find((d: any) => d && d.propName === col.props.prop); return field && field.checked; } onMounted(() => { initSlotList(); // 关键, 初始化插槽 }); </script> <style lang="scss" scoped> .column { &-all { border-bottom: 1px solid #dcdfe6; } &-list { max-height: 300px; overflow: auto; } } </style>
ColumnControl.vue
<!-- 表格列显示隐藏控制 --> <template> <div class="table-toolbar"> <el-button @click="showDialog = true" icon="Grid">表格列</el-button> </div> <el-dialog v-model="showDialog" title="表格列筛选" width="800"> <div class="column-all"> <el-checkbox v-model="checkedAll" :indeterminate="isIndeterminate" @change="onAllChange">全选</el-checkbox> </div> <div class="column-wrap"> <div class="column-checkbox-group" v-if="fields.length > 0"> <div class="column-checkbox" :class="{ active: item.checked }" v-for="(item, index) in fields" :key="index" @click="onItemClick(item)"> <el-tooltip effect="dark" :content="item.label" placement="top" :show-after="300"> {{ item.label }} </el-tooltip> </div> </div> <div class="column-checkbox-group" v-else> <el-empty description="暂无数据" /> </div> </div> </el-dialog> </template> <script setup lang="ts"> interface Field { label: string; propName: string; checked: boolean; } const emit = defineEmits(['update:modelValue', 'change']); // 定义父组件传过来的值 const props = defineProps({ modelValue: { type: Array<Field>, default: () => [], }, }); // 表格列 const fields = ref<Field[]>(props.modelValue); // 全选 const checkedAll = ref(true); // checkbox 的不确定状态 const isIndeterminate = ref(false); // 是否显示对话框 const showDialog = ref(false); /** * 全选 */ function onAllChange(val: boolean) { fields.value.forEach((item: any) => { item.checked = val; }); isIndeterminate.value = false; emit('update:modelValue', fields.value); } function onItemClick(item: any) { item.checked = !item.checked; const checkedCount = fields.value.filter((d: any) => d.checked).length; checkedAll.value = checkedCount === fields.value.length; isIndeterminate.value = checkedCount > 0 && checkedCount < fields.value.length; emit('update:modelValue', fields.value); } // 监听路由的变化,设置网站标题 watch( () => props.modelValue, (newVal) => { fields.value = newVal || []; } ); </script> <style lang="scss" scoped> .table-toolbar { padding-bottom: 8px; display: flex; justify-content: flex-end; } .column { &-wrap { border: 1px solid #d2d2d2; display: flex; min-height: 350px; } &-checkbox { width: 161px; padding: 10px; text-align: center; border-radius: 4px; border: 1px solid #9b9b9b; flex-shrink: 0; margin: 8px; float: left; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; &.active { background-image: url(/@/assets/images/sharedManage/plan/checkbox_selected.png); background-repeat: no-repeat; background-position: right top; border-color: #ff9302; color: #ff9302; } &-group { display: table; flex-wrap: wrap; padding: 4px 8px; } } } </style>
被改造页面
<template> <div class="user-pages"> <div class="user-pages-content"> <ColumnControl v-model="fields"></ColumnControl> <TableControl style="width: 100%" v-model:fields="fields" ref="tableRef" v-loading="state.loading" :data="state.dataList" :height="tableHeight" :header-cell-style="tableStyle.headerCellStyle" show-summary :summary-method="getSummaries" > <el-table-column prop="orderDate" label="月份" align="center" width="" /> <el-table-column prop="companyName" label="所属公司" align="center" width="" /> <el-table-column prop="regionName" label="大区" align="center" width="90" /> <el-table-column prop="" label="区域" align="center" width="" /> <el-table-column prop="province" label="省" align="center" width="" /> <el-table-column prop="city" label="市" align="center" width="" /> <el-table-column prop="area" label="区" align="center" width="" /> </TableControl> <pagination v-bind="state.pagination" @size-change="sizeChangeHandle" @current-change="currentChangeHandle" /> </div> </div> </template> <script setup lang="ts"> // .... import ColumnControl from '/@/components/ColumnControl.vue'; import TableControl from '/@/components/TableControl.vue'; const fields = ref<any[]>([]); // .... </script> <style scoped lang="scss"></style>
效果图