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>
效果图



浙公网安备 33010602011771号