- 需求:实现 表字段的显示与隐藏。
- 效果图
代码实现
写在前面
- 首先 我部分字段有自定义的排序逻辑,和默认值或者 数据的计算 所以是不能简单的使用 v-for 循环column 。
- 然后 我需要默认展示一部分字段,并且 当表无数据时 提示不能 显示隐藏 字段。
- 做一个类表单的设计,在提交的时候才做数据变更,并且添加搜索。
功能实现
因为每个字段的处理不尽相同,所以我采用 v-if 进行控制(注意 v-if 对dom的开销较大,⚠️多字段)。
- 先设置固化数据
- 设置字段信息
- 添加按钮和 el-popover
- 相关函数添加和调试
- 添加搜索框
- 函数添加
- 先设置固化数据
data() {
return {
// 搜索框的输入
popoverSearchQuery: '',
// el-table 的加载值
reload: 1,
// 是否打开 el-popover
popoverVisible: false,
// 选中的列对象数组
selectColumns: [],
// 未选中的列对象数组
unSelectColumns: [],
// checkbox 的model
tempSelectColumns: [],
// 固化的表字段,默认值设置
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-column
label="人员"
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-column
v-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-button
type="text"
plain
class="custom-button"
style="border: none"
icon="el-icon-s-tools"
size="mini"
@click="openSelectPopover"
>筛选字段</el-button>
<el-popover
v-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-input
v-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-checkbox
v-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-checkbox
v-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-button
icon="el-icon-close"
size="mini"
@click="popoverVisible = false"
>取 消</el-button>
<el-button
size="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) {
},
// 打开|关闭 popover
openSelectPopover() {
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的isShow
this.tempSelectColumns.forEach(tsc => {
tsc.isShow = true;
});
this.selectColumns = this.tempSelectColumns;
// 更新columnSetting
this.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