新需求是要支持跨页全选,因为习惯了element的当页全选以及惯性思维,第一步是想到了前端分页,但是这种方法显然是不可取的,因此花了点时间写了个demo分享
因为是个demo,所以就一直按照思路往下写,变量命名没有花心思,if判断也有可优化的地方,后续有空优化后会更新一下代码
如果直接复制完整代码可能会报错,因为项目用了AVUE,删掉这个标签或者安装一个avue就可以,没什么影响
思路:
跨页全选状态下显然不能可传入所有ID(后端分页只拿当前页ID也不可能知道所有ID),所以:
跨页全选状态记录未选中数据(点击跨页全选后,一定能记住未选中ID,因为用户需要手动勾选才能让其 '未选中‘)
非跨页全选状态记录选中数据 (同理)
注意点:
1、跨页全选应该有三种状态(未选,选但是没选完,全选),主要需要注意中间状态 ,因为用户全选后取消勾选某列此时变为 ‘选但是没选完’ 状态,且在用户下一次点击全选按钮,应变为全选状态,而不是未选状态。(有点绕口,实际参考element表格当前页全选切换)
2、翻页时处理选中和未选
<el-checkbox
:indeterminate="indeterminate"
v-model="ifSelectAll"
@change="changeIfSelectAll"
style="margin-left: 20px"
>全部选择</el-checkbox>
<el-table
ref="list"
:data="list"
style="width: 100%"
@select="changeSelect"
@select-all="changeSelectAll"
:row-key="getRowKey"
> </el-table>
indeterminate: false,//控制跨页全选状态
ifSelectAll: false, //是否跨页全选
checkedList: [], //非全选状态下,记录被选中
uncheckedList: [], //全选状态下,记录取消选中
1.监听列表 : 列表数据改变 == 翻页 => 处理选中/未选
2.监听 ‘是否跨页全选’ : 当每次’是否跨页全选改变’ 清空两个记录数组以重新记录
3.监听未选中数组/选中数组:根据选中数量判断当前全选按钮样式以及所处状态
watch: {
list() {
this.backfillSelect();
},
ifSelectAll() {
this.checkedList = [];
this.uncheckedList = [];
},
//监听未选中的数组
uncheckedList: {
handler(value) {
//1.未选中数组长度和总数相等,取消选中状态,取消样式
if (value.length === this.pagination.total) {
this.ifSelectAll = false;
this.indeterminate = false;
}
//2.未选中数组长度为0,取消样式
if (value.length === 0) this.indeterminate = false;
//3.选了但没选完,设置待定样式
if (value.length > 0 && value.length < this.pagination.total)
this.indeterminate = true;
},
deep: true,
},
//监听选中数组
checkedList: {
handler(value) {
if (value.length === this.pagination.total) {
this.ifSelectAll = true;
this.indeterminate = false;
}
if (value.length === 0) this.indeterminate = false;
if (value.length > 0 && value.length < this.pagination.total)
this.indeterminate = true;
},
},
},
//手动勾选数据行
changeSelect(selection, row) {
// 判断勾选数据行是选中还是取消
let selected = selection.length && selection.indexOf(row) !== -1;
if (this.ifSelectAll) {
if (selected) {
// 选中,从未选中数组中去掉
if (this.uncheckedList.length != 0) {
this.uncheckedList.forEach((item, index) => {
if (item.id == row.id) this.uncheckedList.splice(index, 1);
});
}
} else this.uncheckedList.push(row); //取消则记录选中数据
} else {
if (selected) {
if (this.checkedList.indexOf(row) == -1) this.checkedList.push(row);
} else {
if (this.checkedList.indexOf(row) != -1)
this.checkedList.splice(this.checkedList.indexOf(row), 1);
}
}
},
//手动勾选当页全选
changeSelectAll(selection) {
if (this.ifSelectAll) {
// 判断全选本页,是选中还是取消
if (selection.length > 0) {
//选中,从未选中数组中去掉当前页所有数据
this.list.forEach((item) => {
this.uncheckedList.forEach((item_un, index_un) => {
if (item.id == item_un.id) this.uncheckedList.splice(index_un, 1);
});
});
} else {
//取消,未选中的数组中记录该数据
this.list.forEach((item) => {
if (this.uncheckedList.indexOf(item) == -1)
this.uncheckedList.push(item);
});
}
} else {
//非跨页全选状态,记录当前页选中数据
if (selection.length > 0) {
this.list.forEach((item, index) => {
if (this.checkedList.indexOf(item) == -1)
this.checkedList.push(item);
});
} else {
this.list.forEach((item, index) => {
this.checkedList.forEach((item_check, index_check) => {
if (item.id == item_check.id) {
this.checkedList.splice(index_check, 1);
}
});
});
}
}
},
//是否跨页全选
changeIfSelectAll() {
if (this.indeterminate) {
//当不为全选样式时,点击变为全选
this.$nextTick(() => {
this.ifSelectAll = true;
this.backfillSelect();
});
}
if (this.ifSelectAll) this.backfillSelect();
else this.clearSelect();
},
//回填选中
backfillSelect() {
this.$nextTick(() => {
//跨页全选记录未选中
if (this.ifSelectAll) {
this.list.forEach((item, index) => {
if (this.uncheckedList.length > 0) {
let ifSelection = true;
this.uncheckedList.forEach((item_un) => {
if (item.id == item_un.id) ifSelection = false;
});
if (ifSelection)
this.$refs.list.toggleRowSelection(this.list[index], true);
} else this.$refs.list.toggleRowSelection(this.list[index], true);
});
//非跨页全选记录选中
} else {
if (this.checkedList.length > 0) {
this.list.forEach((item, index) => {
let ifSelection = false;
this.checkedList.forEach((item_check) => {
if (item.id == item_check.id) ifSelection = true;
});
if (ifSelection)
this.$refs.list.toggleRowSelection(this.list[index], true);
});
}
}
});
},
//全部取消选中
clearSelect() {
this.$nextTick(() => {
this.$refs.list.clearSelection();
});
},
selectGoods.vue
<!--
* @Author: hwd
* @Description: 选择商品
* @FilePath: \tik-tok-crm\src\views\tiktok\equityManage\integral\selectGoods.vue
-->
<template>
<el-dialog
title="选择商品"
v-dialogdrag
:visible="true"
class="avue-dialog"
width="1300px"
:close-on-click-modal="false"
:before-close="
() => {
$emit('close');
}
"
>
<el-form :inline="true" label-width="120px" :model="query">
<el-form-item label="商品名称:">
<el-input
v-model="query.name"
size="small"
style="width: 200px"
placeholder="请输入商品名称"
></el-input>
</el-form-item>
<el-form-item label="商品名称ID:">
<el-input
size="small"
style="width: 200px"
placeholder="请输入商品名称ID"
></el-input>
</el-form-item>
<el-form-item label="商品状态:">
<el-select size="small" v-model="query.status" placeholder="请选择">
</el-select>
</el-form-item>
<el-form-item style="margin-right: 50px" label="售 价 :">
<el-input size="small" style="width: 94px"></el-input> -
<el-input size="small" style="width: 94px"></el-input>
</el-form-item>
<el-form-item label="">
<el-button size="small" type="primary">查询</el-button>
<el-button size="small">重置</el-button>
<el-checkbox :indeterminate="indeterminate" v-model="ifSelectAll" @change="changeIfSelectAll" style="margin-left: 20px">全部选择</el-checkbox >
</el-form-item>
</el-form>
<el-table
ref="list"
:data="list"
style="width: 100%"
@select="changeSelect"
@select-all="changeSelectAll"
:row-key="getRowKey"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="date" label="商品" width="300">
<template slot-scope="scope">
<div class="goodsMsg">
<el-image class="left image" :src="scope.row.imgUrl"></el-image>
<div class="right">
<avue-text-ellipsis
:key="scope.row.id"
:text="scope.row.name"
:height="40"
:width="200"
use-tooltip
placement="top"
>
<small slot="more">...</small>
</avue-text-ellipsis>
<el-tag type="success" size="mini">{{ scope.row.id }}</el-tag>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="id" label="售价" width="180"> </el-table-column>
<el-table-column prop="销量" label="销量"> </el-table-column>
<el-table-column prop="库存" label="库存"> </el-table-column>
<el-table-column prop="状态" label="状态">
<template slot-scope="scope">
<el-tag type="info">下架</el-tag>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pagination"
background
@size-change="sizeChange"
@current-change="currentChange"
layout="total, sizes, prev, pager, next, jumper"
:page-size="pagination.size"
:page-sizes="[10, 50, 100]"
:current-page="pagination.current"
:total="pagination.total"
>
</el-pagination>
<div class="avue-dialog__footer">
<el-button @click="$emit('close')">取 消</el-button>
<el-button @click="handleClick" type="primary">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { getGoods } from "./test";
export default {
data() {
return {
indeterminate: false,//跨页全选状态变换
ifSelectAll: false, //是否跨页全选
checkedList: [], //非全选状态下,记录被选中
uncheckedList: [], //全选状态下,记录取消选中
activeName: "first",
query: {},
ifShowEdit: true,
pagination: {
total: 20,
current: 1,
size: 10,
},
list: [],
};
},
components: {},
watch: {
list() {
this.backfillSelect();
},
ifSelectAll: {
handler() {
this.checkedList = [];
this.uncheckedList = [];
},
},
//监听未选中的数组
uncheckedList: {
handler(value) {
//1.未选中数组长度和总数相等,取消选中状态,取消样式
if (value.length === this.pagination.total) {
this.ifSelectAll = false;
this.indeterminate = false;
}
//2.未选中数组长度为0,取消样式
if (value.length === 0) this.indeterminate = false;
//3.选了但没选完,设置待定样式
if (value.length > 0 && value.length < this.pagination.total)
this.indeterminate = true;
},
deep: true,
},
//监听选中数组
checkedList: {
handler(value) {
if (value.length === this.pagination.total) {
this.ifSelectAll = true;
this.indeterminate = false;
}
if (value.length === 0) this.indeterminate = false;
if (value.length > 0 && value.length < this.pagination.total)
this.indeterminate = true;
},
},
},
created() {
this.getGoods(1);
},
methods: {
getRowKey(row) {
return row.id;
},
//手动勾选数据行
changeSelect(selection, row) {
// 判断勾选数据行是选中还是取消
let selected = selection.length && selection.indexOf(row) !== -1;
if (this.ifSelectAll) {
if (selected) {
// 选中,从未选中数组中去掉
if (this.uncheckedList.length != 0) {
this.uncheckedList.forEach((item, index) => {
if (item.id == row.id) this.uncheckedList.splice(index, 1);
});
}
} else this.uncheckedList.push(row); //取消则记录选中数据
} else {
if (selected) {
if (this.checkedList.indexOf(row) == -1) this.checkedList.push(row);
} else {
if (this.checkedList.indexOf(row) != -1)
this.checkedList.splice(this.checkedList.indexOf(row), 1);
}
}
},
//手动勾选当页全选
changeSelectAll(selection) {
if (this.ifSelectAll) {
// 判断全选本页,是选中还是取消
if (selection.length > 0) {
//选中,从未选中数组中去掉当前页所有数据
this.list.forEach((item) => {
this.uncheckedList.forEach((item_un, index_un) => {
if (item.id == item_un.id)
this.uncheckedList.splice(index_un, 1);
});
});
} else {
//取消,未选中的数组中记录该数据
this.list.forEach((item) => {
if (this.uncheckedList.indexOf(item) == -1)
this.uncheckedList.push(item);
});
}
} else {
//非跨页全选状态,记录当前页选中数据
if (selection.length > 0) {
this.list.forEach((item, index) => {
if (this.checkedList.indexOf(item) == -1)
this.checkedList.push(item);
});
} else {
this.list.forEach((item, index) => {
this.checkedList.forEach((item_check, index_check) => {
if (item.id == item_check.id) {
this.checkedList.splice(index_check, 1);
}
});
});
}
}
},
//是否跨页全选
changeIfSelectAll() {
if (this.indeterminate) {
//当不为全选样式时,点击变为全选
this.$nextTick(() => {
this.ifSelectAll = true;
this.backfillSelect();
});
}
if (this.ifSelectAll) this.backfillSelect();
else this.clearSelect();
},
//回填选中
backfillSelect() {
this.$nextTick(() => {
//跨页全选记录未选中
if (this.ifSelectAll) {
this.list.forEach((item, index) => {
if (this.uncheckedList.length > 0) {
let ifSelection = true;
this.uncheckedList.forEach((item_un) => {
if (item.id == item_un.id) ifSelection = false;
});
if (ifSelection)
this.$refs.list.toggleRowSelection(this.list[index], true);
} else this.$refs.list.toggleRowSelection(this.list[index], true);
});
//非跨页全选记录选中
} else {
if (this.checkedList.length > 0) {
this.list.forEach((item, index) => {
let ifSelection = false;
this.checkedList.forEach((item_check) => {
if (item.id == item_check.id) ifSelection = true;
});
if (ifSelection)
this.$refs.list.toggleRowSelection(this.list[index], true);
});
}
}
});
},
//全部取消选中
clearSelect() {
this.$nextTick(() => {
this.$refs.list.clearSelection();
});
},
//获取商品列表
getGoods(type) {
this.list = getGoods(type);
},
handleClick() {
if (this.ifSelectAll) console.log("全选", this.uncheckedList);
else console.log("非全选", this.checkedList);
},
sizeChange(val) {
this.getGoods(val);
},
currentChange(val) {
this.getGoods(val);
},
},
};
</script>
<style lang="scss" scoped>
.image {
width: 50px;
height: 50px;
border-radius: 5px;
}
.goodsMsg {
display: flex;
.left {
margin-right: 10px;
}
}
</style>
test.js
/*
* @Author: hwd
* @Description:
* @FilePath: \tik-tok-crm\src\views\tiktok\equityManage\integral\test.js
*/
export function getGoods(type) {
// return request({
// url: '/gen/dsconf/',
// method: 'put',
// data: obj
// })
let list = [
{
id: 1,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 2,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 3,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 4,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 5,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 6,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 7,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 8,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 9,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 10,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 11,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 12,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 13,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 14,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 15,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 16,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 17,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 18,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 19,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
{
id: 20,
imgUrl:
"https://p9-aio.ecombdimg.com/obj/ecom-shop-material/v1_rXNkLqu_70812225812687751790881_3c057df3070c0b6ca54368b17ed9c644_sx_242657_www800-800",
name: "商品名称,商品名称商品名称商品名称商品名称商品名称商品名称",
},
];
if (type == 1) return list.slice(0, 10);
if (type == 2) return list.slice(10, 20);
}