<template>
<div class="app">
<div>
<el-checkbox v-model="crossPage">跨页全选</el-checkbox>
</div>
<el-table
ref="tableRef"
:data="dataRender"
row-key="id"
:columns="columns"
border
stripe
@select="onSelect"
@selection-change="onSelectionChange"
>
<el-table-column type="selection" />
<el-table-column
:prop="item.dataIndex"
:label="item.title"
:width="item.width"
v-for="item in columns"
:key="item.dataIndex"
/>
</el-table>
<div class="pagination">
<el-pagination
layout="total, prev, pager, next"
@current-change="onPageChange"
:total="pagination.total"
/>
</div>
<div>
<div v-if="crossPage">排除:{{ JSON.stringify(excludeSelected) }}</div>
<div v-else>已选择:{{ JSON.stringify(selection) }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch, nextTick } from "vue";
import axios from "axios";
import { changeArr } from "../utils/arr-helper";
// 分页信息
const pagination = reactive({
current: 1,
pageSize: 10,
total: 5,
showTotal: true,
});
// 表头
const columns = [
{
title: "姓名",
dataIndex: "name",
width: 100,
},
{
title: "年龄",
dataIndex: "age",
width: 100,
},
{
title: "工资",
dataIndex: "salary",
width: 100,
},
{
title: "住址",
dataIndex: "address",
},
];
const dataRender = ref([]);
const syncDataRender = async () => {
const {
data: { data },
} = await axios.get("/api/user", {
params: {
current: pagination.current,
pageSize: pagination.pageSize,
},
});
dataRender.value = data.list;
pagination.total = data.total;
};
syncDataRender();
const onPageChange = async (current) => {
pagination.current = current;
syncDataRender();
};
// 跨页全选要立即选中当前页数据,即便翻页的也要选中,但是不能包含排除的
// 需要注意的是:当勾选了跨页全选后,已经选中的就不在作数,而是重点关注排除项
// 记录 excludeSelected
// 用户手动勾选触发
// 主要用于记录用户手动取消勾选的项,用于跨页全选时排除
const excludeSelected = ref([]);
const onSelect = (selection, row) => {
const isSelected = selection.findIndex((item) => item.id === row.id) > -1; // 本次是选中还是取消
if (crossPage.value) {
excludeSelected.value = changeArr({
arr: excludeSelected.value,
row,
action: isSelected ? "rm" : "push",
});
}
};
// 记录 selection
// 当选择项发生变化时会触发该事件(包含手动or 调用 tableRef.value.toggleRowSelection)
const selection = ref([]);
const onSelectionChange = (arg) => {
selection.value = arg;
};
// 当跨页全选时,要选中当前页的所有数据
const crossPage = ref(false);
const tableRef = ref(null);
watch(
() => crossPage.value,
() => {
if (crossPage.value) {
for (const element of dataRender.value) {
tableRef.value.toggleRowSelection(element, true);
}
} else {
excludeSelected.value = [];
}
}
);
// 跨页全选时,即便内容变化(如翻页)的也要选中,但是不能包含排除的
watch(
() => dataRender.value,
async () => {
// 这里要做还原选中状态
if (crossPage.value) {
for (const element of dataRender.value) {
const isExclude = excludeSelected.value.findIndex((item) => item.id === element.id) >-1;
if (!isExclude) {
await nextTick();
tableRef.value.toggleRowSelection(element, true);
}
}
}
}
);
</script>
<style>
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
</style>
