前言
最近后管项目新加了一个需求,需要在原有的列表上加一个全选按钮,实现对整个列表或者筛选后的整个列表数据进行一个整体的操作。
看了下
Element
中的el-table
文档,并没有现成的API
,只好自己实现。大概的思路就是切换页面时将当前页面的数据勾选中(当然其中也踩了几个坑🕳,捋清思路实现起来其实也很简单( •̀ ω •́ )y)。
1. 添加一个跨页全选按钮
- 绑定跨页数组
state.pageChecked
- 绑定跨页全选方法
checkAll
<el-checkbox
v-model="state.pageChecked"
label="全选"
@change="checkAll"
:disabled="!state.total" />
2.table设置如下
- 在el-table中添加
- 表格内全选:@select-all="
selectAll
" - 表格内行勾选:@select="
changeSelect
" - 指定唯一标识符为row.id:
:row-key
="getRowKeys"
- 表格内全选:@select-all="
- 在el-table-column中添加
- 设置为勾选项:
type="selection
" :reserve-selection="true"
: 当数据发生变化时,保留之前的选择状态,即使数据重新加载或分页切换,已选中的行仍然会被记住,需要table配合使用:row-key来指定唯一标识符
- 设置为勾选项:
<el-table
v-loading="state.loading"
:data="state.tableData"
@select-all="selectAll"
@select="changeSelect"
ref="tableRef"
:row-key="getRowKeys">
<el-table-column type="selection" width="55" :reserve-selection="true" />
</el-table>
3.调用接口获取数据
- 实现跨页全选其实就是切换页面时将当前页面的数据勾选中
- 选中的是当前页的数据,但是需要先判断当前页的每一行是否都存在跨页全选的数组中(state.tableData永远都是当前页全部数据,但state.saveCheckList可能在某一页不是全选,以state.saveCheckList为准来勾选)
const getTableData = () => {
state.loading = true;
student_list(query)
.then(res => {
if (res.code == 200 && res.data) {
let result = res.data || [];
state.tableData = result;
state.tableData.forEach((row) => {
let findex = state.saveCheckList.findIndex((item) => {
return item.id == row.id;
});
if (findex >= 0) {
tableRef.value.toggleRowSelection(row, true);
}
});
state.total = res.total;
}
})
.finally(() => {
state.loading = false;
});
};
4.当前行勾选或取消(changeSelect)
- 全选用
push
加入 - 反选用
splice
删除
const changeSelect = (selection, row) => {
console.log('tableChangeSelect',row);
let fitemIndex = state.saveCheckList.findIndex((item) => {
return item.id == row.id;
});
if (fitemIndex < 0) {
state.saveCheckList.push(row);
} else {
state.saveCheckList.splice(fitemIndex, 1);
}
if (state.saveCheckList.length === state.total) {
state.pageChecked = true
} else {
state.pageChecked = false
}
}
5.表格内全选(selectAll)
- 反选
- 每次点击切换分页,都会触发接口获取当前页的10条数据,并赋值给state.tableData
- 当跨页全选时,在某一页点击取消全选当前页,需要把当前页的数据在跨页全选的数据中去除
- 全选
- 当跨页全选时,在某一页点击取消全选当前页再点击全选当前页,需要把当前页的数据在跨页全选的数据中加上
- 如果跨页数组的长度等于列表全部数量,勾选跨页选中,否则取消
const selectAll = (val) => {
if (val && val.length == 0) {
console.log(val.length);
state.tableData.forEach((row) => {
let fitemIndex = state.saveCheckList.findIndex((item) => {
return item.id == row.id;
});
if (fitemIndex >= 0) {
state.saveCheckList.splice(fitemIndex, 1);
}
});
} else if (val && val.length != 0 ) {
val.forEach((row) => {
let fitemIndex = state.saveCheckList.findIndex((item) => {
return item.id == row.id;
});
if (fitemIndex < 0) {
state.saveCheckList.push(row);
}
});
}
if (state.saveCheckList.length === state.total) {
state.pageChecked = true
} else {
state.pageChecked = false
}
}
6.跨页全选(checkAll)
- 全选
- 跨页全选使用总数量调接口赋值给跨页数组
- 使用
toggleAllSelection()
将当前页全选
- 反选
- 将跨页数组清空
- 使用
clearSelection()
取消当前页全选
const checkAll = (selection, row) => {
state.loading = true
if (state.pageChecked) {
student_list({ ...query, size: state.total, page: 1 }).then((res) => {
if (res.code == 200 && res.data) {
state.saveCheckList = res.data;
tableRef.value.clearSelection();
tableRef.value.toggleAllSelection();
state.loading = false
}
});
} else {
state.saveCheckList = [];
tableRef.value.clearSelection();
state.loading = false
}
}
至此,已经完成了基于el-table实现跨页全选反选,以及保留el-table原有的单项复选和整页全选反选。
ps:因为每次点击跨页全选反选都会触发接口查询数据,如果table数据较大且接口较慢,会出现列表回显缓慢的情况,建议添加loading和disabled效果,防止频繁点击和列表卡顿