概述
在后台管理系统,前台列表展示,时不时会碰到需要进行全选,反选操作,然后进行批量操作逻辑,最常见的要属后台的列表,以及前台需要做购物车的时候批量结算,或者阅读图书批量删除书签,笔记等等操作。本质上,都是表格结合checkbook进行的批量操作,学会一种,业务中基本上所有的这种批量选中操作思路基本都一样。
使用场景示例
- 后台表格
- 前台列表
最终效果
目录结构
App.vue
<template>
<div id="app">
<edit-table
:tableDta="tableDta"
:headData="headData"
:allSelectTip="allSelectTip"
:selectChange="handleSelectChange"
:showEdit="showEdit"
></edit-table>
</div>
</div>
</template>
<script>
import EditTable from "./components/EditTable/EditTable.vue";
export default {
name: "App",
components: {
EditTable,
},
data() {
return {
//表格数据
tableDta: [
{
id: 1,
chinase: 123,
math: 111,
english: 98,
chemistry: 56,
},
{
id: 2,
chinase: 100,
math: 99,
english: 123,
chemistry: 88,
},
{
id: 3,
chinase: 134,
math: 34,
english: 98,
chemistry: 76,
},
{
id: 4,
chinase: 56,
math: 22,
english: 123,
chemistry: 111,
},
],
//表头全选,反选,提示文字
allSelectTip: {
confirm: "全部选中",
cancel: "取消全选",
},
//表头不数据
headData: [
{
id: 1,
title: "语文",
},
{
id: 2,
title: "数学",
},
{
id: 3,
title: "英语",
},
{
id: 4,
title: "化学",
},
{
id: 5,
title: "操作",
},
],
//是否显示checkbox
showEdit: true,
};
},
methods: {
handleSelectChange(list) {
console.log(list);
},
},
};
</script>
.components/EditTable/EditTable.vue
<template>
<div class="edit-table">
<!-- 表格数据 -->
<table>
<!-- 表头部分 -->
<thead>
<tr>
<th v-if="showEdit">
<!-- 表头checkbox组件:选中项的长度和表格数据长度一致的时候,表示全部全部选中 -->
<check-box
:text="checkBoxText"
@change="handleAllChange"
:checked="checkData.length == originData.length"
></check-box>
</th>
<th v-for="item in headData" :key="item.id">{{ item.title }}</th>
</tr>
</thead>
<!-- 表格主体部分 -->
<tbody>
<tr v-for="item in originData" :key="item.id">
<!-- 表格主体checkbox组件:当前列在选中项中说明选中了.反之没有 -->
<td v-show="showEdit">
<check-box
:checked="checkData.some((data) => data.id == item.id)"
@change="(checked) => handleItemChange(checked, item)"
></check-box>
</td>
<td v-for="subject in fieldList" :key="subject">
{{ item[subject] }}
</td>
<!-- 删除当前列 -->
<td><button @click="handleDel(item)">删除</button></td>
</tr>
</tbody>
</table>
<!-- 批量操作 -->
<div class="operate-group">
<button @click="handleBatchOperate('all')">全选</button>
<button @click="handleBatchOperate('cancel')">取消</button>
<button @click="handleBatchOperate('del')">删除</button>
</div>
</div>
</template>
<script>
// checkbox组件
import CheckBox from "./CheckBox";
export default {
components: {
CheckBox,
},
props: {
// 表格数据
tableDta: {
type: Array,
default() {
return [];
},
},
// 表头
headData: {
type: Array,
default() {
return [];
},
},
// 权限,反选文字
allSelectTip: {
type: Object,
default() {
return {};
},
},
// 选中项变化需要执行的函数
selectChange: {
type: Function,
default() {
return () => {};
},
},
// 是否需要显示第一列checkbox
showEdit: {
type: Boolean,
default: false,
},
},
data() {
return {
// 保存选中项
checkData: [],
// 备份表格数据项
originData: this.tableDta,
};
},
computed: {
// 动态计算全选,反选文字
checkBoxText() {
return this.checkData.length == this.originData.length
? this.allSelectTip.confirm
: this.allSelectTip.cancel;
},
/**
* @Description 表格需要渲染的字段
* {
id: 1,
chinase: 123,
math: 111,
english: 98,
chemistry: 56,
},
我们需要排除id字段,id字段仅仅做key标识,不需要渲染到列表当中
*
**/
fieldList() {
return this.tableDta.length
? Object.keys(this.tableDta[0]).filter((item) => item != "id")
: [];
},
},
methods: {
//点列checkbox点击
handleItemChange(checked, data) {
if (checked) {
// checkbox为true的时候,表示添加
this.checkData = [...this.checkData, data];
} else {
// checkbox为true的时候,表示删除
this.checkData = this.checkData.filter((item) => item.id != data.id);
}
// 执行用户传进来的监听选中项变化的函数
this.selectChange(this.checkData);
},
// 所有checkbox点击
handleAllChange(checked) {
checked ? (this.checkData = [...this.originData]) : (this.checkData = []);
// 执行用户传进来的监听选中项变化的函数
this.selectChange(this.checkData);
},
// 删除单个
handleDel(data) {
// 过滤掉当前项
this.originData = this.originData.filter((item) => data.id != item.id);
// 同步选中项
this.checkData = this.checkData.filter((item) => data.id != item.id);
},
// 批量删除
batchDel() {
// 循环选中项,执行过滤操作
this.checkData.forEach((item) => {
this.handleDel(item);
});
},
// 批量操作
handleBatchOperate(type) {
switch (type) {
case "all":
this.handleAllChange(true);
break;
case "cancel":
this.handleAllChange(false);
break;
case "del":
this.batchDel();
break;
}
},
},
};
</script>
<style lang="less">
.edit-table {
table {
width: 500px;
border-collapse: collapse;
text-align: center;
}
table,
tr,
td,
th {
border: 1px solid #ccc;
}
.operate-group {
}
}
</style>
.components/EditTable/CheckBox.vue
<template>
<div>
<input
type="checkbox"
:checked="checked"
@change="$emit('change', $event.target.checked)"
/>
{{ text }}
</div>
</template>
<script>
export default {
props: {
checked: Boolean,
text: {
type: String,
default: "",
},
},
};
</script>
<style lang="less"></style>
总结
掌握上面表格的基本思路之后,如果你项目里面有类似的全选,反选,操作,都可以套用这种写法,思路基本上都是类似的,剩下的可以自己扩展。