前言:
el-table其实自带多选功能,手动添加一个el-table-column
,设type
属性为selection
,再绑定一个方法@selection-change="handleSelectionChange"即可拿到多选的数据。
但当涉及到接口分页以及勾选数据回显的时候,这个方法就不好用了。
以下介绍一种使用el-check来模拟el-table的勾选功能的写法。
效果图:
左右两边共用一份数据源selectedData,同步添加和删除,保证表格翻页(调后端接口)也能实现回显效果
实现思路:
1、写一个方法,来判断当前行数据有没有被勾选
- 如果是checkbox的点击事件中调用(不论是全选还是单选),则传一个参数type(因为是在for循环中,如果直接返回布尔值可能会阻断循环,这样就不能做全选的遍历了)。如果当前数据在已勾选数组中,则返回它的下标,如果不在则返回-1;
- 如果是el-table中判断当前数据是否被勾选,第二个参数不必传。勾选了则返回true,没勾选返回false。
isExist(row, type) {
for (let i in this.selectedData) {
if (this.selectedData[i].id === row.id) {
return type === 'index'? i : true
}
}
return type === 'index'? -1 : false
},
2、写一个checkbox,定位到表头,代替全选框。
绑定一个布尔值selectAll,默认为false,在每次调取列表接口的时候都重置为false值,保证获取新数据时都可以勾选(这里有个bug,这个值没有半选效果,也不能回显,因为要回显的话得反向判断这一页的每条数据时候是否都勾选上,比较麻烦)
<el-checkbox class="check-all-btn" v-model="selectAll" @change="selectAllChange"></el-checkbox>
全选事件selectAllChange的逻辑,遍历表格数据,在操作前先通过方法isExist()返回的值来判断当前行是否勾选。如果点击了全选&&返回-1(代表没被勾选),即可添加到勾选数组中;如果取消了全选&&返回值不等于-1(被勾选上了),则在数组中删除此条数据
selectAllChange(val) {
this.tableData.map(item => {
let idx = this.isExist(item, 'index')
if(val && idx === -1 && !item.type) { //只能添加未推广的宝贝 type=1已推广
if(this.selectedData.length >= this.canSelectNum) return false
this.selectedData.push(item)
} else if(!val && idx != -1) {
this.selectedData.splice(idx, 1);
}
})
},
3、表格第一列是勾选框,根据方法isExist()返回的布尔值判断是否勾选。
勾选事件selectChange的逻辑,在操作前先通过方法isExist()返回的值来判断当前行是否勾选。如果是点击勾选&&返回-1,即可添加到勾选数组中;如果是取消勾选&&返回值不等于-1(被勾选上了),则在数组中删除此条数据
<el-table-column align="center" width="50">
<template v-slot="scope">
<el-checkbox :value="isExist(scope.row)" :disabled="scope.row.type===1"
@change="(val) => selectChange(val, scope.row)"></el-checkbox>
</template>
</el-table-column>
selectChange(val, row) {
if(val && this.selectedData.length >= this.canSelectNum) return false
let idx = this.isExist(row, 'index')
if(val && idx === -1 && !row.type) { //只能添加未推广的宝贝 type=1已推广
this.selectedData.push(row)
}else if(!val && idx != -1) {
this.selectedData.splice(idx, 1);
this.selectAll = false;
}
},
以下是全部代码:
<div style="position: relative" class="mt-6">
// 写一个checkbox,定位到表头,代替全选框
<el-checkbox class="check-all-btn" v-model="selectAll" @change="selectAllChange"></el-checkbox>
<el-table :data="tableData" :max-height="tableHeight" style="width:100%"
v-loading="loading"
element-loading-spinner="el-icon-loading yb-loading"
highlight-current-row
@sort-change="sortChange">
// 第一列是勾选框,根据方法isExist返回的布尔值判断是否勾选
<el-table-column align="center" width="50">
<template v-slot="scope">
<el-checkbox :value="isExist(scope.row)" :disabled="scope.row.type===1"
@change="(val) => selectChange(val, scope.row)"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="宝贝" min-width="240">
<template v-slot="scope">
<div class="flex flex-align-center">
<el-popover v-if="!!scope.row.imgUrl" placement="right" width="400" trigger="hover">
<img :src="scope.row.imgUrl" />
<div slot="reference" class="mr-2 img-box"
style="width: 4rem; height: 4rem"
:style="'background-image: url(' + scope.row.imgUrl + ')'"></div>
</el-popover>
<div>
<p class="text-overflow-2" :title="scope.row.title">{{ scope.row.title }}</p>
<p class="color999">宝贝ID:{{ scope.row.itemId }}</p>
<el-tag size="mini" v-if="scope.row.type">已推广</el-tag>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="quantity" label="销量" width="80"
sortable='custom' :sort-orders="['descending', 'ascending', null]">
</el-table-column>
<el-table-column prop="bidCount" label="库存" width="80"
sortable='custom' :sort-orders="['descending', 'ascending', null]"></el-table-column>
<el-table-column prop="starts" label="发布日期" width="140"
sortable='custom' :sort-orders="['descending', 'ascending', null]"></el-table-column>
</el-table>
<el-pagination :current-page="params.pageIndex"
:page-size="params.pageSize"
:total="total"
:page-sizes="[5, 10, 20, 50, 100]"
layout="total, sizes, prev, pager, next,jumper"
@size-change="handleSizeChange"
@current-change="handlePageChange">
<span style="float: left; margin-left: 20px">
共 <span style="color: #17b8be; min-width: auto">{{ total }}</span> 条
</span>
</el-pagination>
</div>