- 需求:实现 表字段的显示与隐藏。
- 效果图
代码实现
写在前面
- 首先 我部分字段有自定义的排序逻辑,和默认值或者 数据的计算 所以是不能简单的使用 v-for 循环column 。
- 然后 我需要默认展示一部分字段,并且 当表无数据时 提示不能 显示隐藏 字段。
- 做一个类表单的设计,在提交的时候才做数据变更,并且添加搜索。
功能实现
因为每个字段的处理不尽相同,所以我采用 v-if 进行控制(注意 v-if 对dom的开销较大,⚠️多字段)。
- 先设置固化数据
- 设置字段信息
- 添加按钮和 el-popover
- 相关函数添加和调试
- 添加搜索框
- 函数添加
- 先设置固化数据
data() {return {// 搜索框的输入popoverSearchQuery: '',// el-table 的加载值reload: 1,// 是否打开 el-popoverpopoverVisible: false,// 选中的列对象数组selectColumns: [], // 未选中的列对象数组unSelectColumns: [], // checkbox 的modeltempSelectColumns: [], // 固化的表字段,默认值设置columnSetting: [// {prop: 'userChineseName', label: '人员', isShow: true},{prop: 'onDutyDays', label: '实际出勤天数', isShow: true},{prop: 'avgDutyMinutesPerDutyDay', label: '平均每日出勤时长(小时)', isShow: true},{prop: 'avgTaskMinutesPerDutyDay', label: '平均每日任务时长(小时)', isShow: true},{prop: 'taskNum', label: '任务数', isShow: true},{prop: 'bugOverview', label: '产出Bug', isShow: true},{prop: 'caseOverview', label: '产出Case', isShow: true},{prop: 'codeOverview', label: '产出代码', isShow: true},{prop: 'userGroupName', label: '当前所属团队', isShow: false},{prop: 'userLevel', label: '人员职级', isShow: false},{prop: 'theoreticalOnDutyDays', label: '应出勤天数', isShow: false},{prop: 'otDays', label: '加班天数', isShow: false},{prop: 'absenteeismDays', label: '旷工天数', isShow: false},{prop: 'afterPunchDays', label: '补卡天数', isShow: false},{prop: 'tagCount', label: '标注件数', isShow: false},{prop: 'rewardTagCount', label: '悬赏数', isShow: false}]}
}
- 设置字段信息
要明确一点:要不要有默认展示字段(即:当所有字段不勾选时,展示什么字段数据)
<!-- 人员默认展示,即对该字段不做判断 -->
<el-table-columnlabel="人员"width="200px"align="center"fixed="left"
><template slot-scope="scope">{{ `${scope.row.userChineseName}(${scope.row.username})` }}</template>
</el-table-column><!-- v-if实现字段的显示隐藏 参数为prop或者唯一值即可 -->
<el-table-columnv-if="showColumn('onDutyDays')"label="实际出勤天数"align="center"prop="onDutyDays"sortable="custom"min-width="80"
>
<template slot-scope="scope"><div>{{ scope.row.onDutyDays }}</div></template>
</el-table-column>
- 添加页面和触发按钮(搜索框和 checkbox)
<!--添加字段筛选-->
<div><el-buttontype="text"plainclass="custom-button"style="border: none"icon="el-icon-s-tools"size="mini"@click="openSelectPopover">筛选字段</el-button><el-popoverv-model="popoverVisible"placement="bottom-end"trigger="click"class="my-popover"><!-- 搜索 --><!-- 搜索框容器,使用position: sticky来使其在页面滚动时保持在顶部 --><div class="search-bar-container" style="position: sticky; top: 0; z-index: 10; background-color: white;"><el-inputv-model="popoverSearchQuery"suffix-icon="el-icon-search"placeholder="搜索"clearable@suffix-click="handlePopoverSearchQuery"></el-input></div><div class="columns-filter"><!-- 已选中的项 --><div v-if="selectColumns.length > 0"><h3 style="margin-top: -10px;color: #d76969;">已选择</h3><div v-for="(column, index) in selectColumns" :key="column.prop"><el-checkboxv-model="tempSelectColumns":label="column":value="column"@change="selectHandleCheckboxChange(column)">{{ column.label }}</el-checkbox></div><hr> <!-- 已选中与未选中之间的横线 --></div><!-- 未选中的项 --><div v-for="(column, index) in unSelectColumns" :key="column.prop"><el-checkboxv-model="tempSelectColumns":label="column":value="column"@change="selectHandleCheckboxChange(column)">{{ column.label }}</el-checkbox></div><br><div slot="footer" style="display: flex; justify-content: center;"><el-buttonicon="el-icon-close"size="mini"@click="popoverVisible = false">取 消</el-button><el-buttonsize="mini"icon="el-icon-check"type="primary"@click="confirmSelection">确 定</el-button></div></div></el-popover>
</div><!--样式 -->
<style lang="scss" scoped>
// 按钮样式设计, 右上角
.custom-button{float: right;margin-right: 50px;margin-top: -6px;font-size: 13px;
}
// 鼠标悬浮 改变背景色
.custom-button:hover {background-color: transparent;color: #ad64a4;
}
// popover位置设置
.my-popover {float: right;margin-right: 130px;margin-top: 20px;
}
// popover 内部设置最高和滚动条
.columns-filter {max-height: 270px;overflow-y: auto;padding: 10px;font-size: 15px;
}
</style>
- 相关函数添加和调试
// input 值发生变动就进行搜索
watch: {popoverSearchQuery(newVal) {if (!newVal) {this.resetColumns();}else {this.filterColumns();}}
}
// 初始化
created() {this.initColumn();
},
methods: {// 搜索相关-前端实现handlePopoverSearchQuery() {this.filterColumns();},filterColumns() {this.selectColumns = this.columnSetting.filter(column => column.isShow && column.label.includes(this.popoverSearchQuery));this.unSelectColumns = this.columnSetting.filter(column => !column.isShow && column.label.includes(this.popoverSearchQuery));if (!this.popoverSearchQuery) {this.resetColumns();}},resetColumns() {this.selectColumns = this.columnSetting.filter(column => column.isShow);this.unSelectColumns = this.columnSetting.filter(column => !column.isShow);},// 初始化 给 选中和未选中赋值initColumn() {this.selectColumns = this.columnSetting.filter(column => column.isShow);this.unSelectColumns = this.columnSetting.filter(column => !column.isShow);// 设置checkbox中值为已选中的值this.tempSelectColumns = [...this.selectColumns];},// 计算是否需要展示showColumn(currentColumn) {return this.columnSetting.find(item => item.prop === currentColumn).isShow;},// onclick 按需 添加逻辑,如果不需要 点确定再触发方法 就可以将 confirmSelection 拿到 该函数中。selectHandleCheckboxChange(column) {},// 打开|关闭 popoveropenSelectPopover() {if (this.gridData.length < 1) {Message.warning('当前列表数据,暂无法使用筛选功能~ ');return;}if (this.popoverVisible) {this.popoverVisible = false;}else {this.popoverVisible = true;this.popoverSearchQuery = '';}},// 触发数据 处理 confirmSelection() {const unSelectColumns = this.columnSetting.filter(col =>!this.tempSelectColumns.some(tsc => tsc.prop === col.prop)).map(col => ({...col, isShow: false}));this.unSelectColumns = unSelectColumns;// 更新tempSelectColumns的isShowthis.tempSelectColumns.forEach(tsc => {tsc.isShow = true;});this.selectColumns = this.tempSelectColumns;// 更新columnSettingthis.columnSetting = [...this.tempSelectColumns, ...unSelectColumns];// 这里可以添加额外的处理逻辑,比如发送请求等this.popoverVisible = false;}
}
fix:
提交 确定 之后 表格会闪烁一下 再显示字段。这是因为dom要重新加载 被销毁的元素。
解决方案 :
el-table 添加 :key=“reload”
<el-table:key="reload"style="margin-right: 30px":header-row-style="{background: '#f5f5f5',padding: '0',color: 'black',fontSize: '12px',}">
</el-table>
watch: {columnSetting (newVal) {// 解决表格闪烁this.reload = Math.random();}
}
end