该博客介绍的功能适用于什么场景?
当使用Table做数据展示,并需要多选时,如果数据都在同一页,可以直接使用官方文档里的demo就可以轻松实现。但如果对数据做了分页展示处理,如何实现在多个页面间选择呢?这里主要记录我的实现方式。
我是基于element做的,若是基于iviewui做,思路也相通。element中对于多选Table的demo如下:element多选Table,这里不再对demo代码进行解释。

思路介绍
该问题的难点在于JS部分,当用户进行勾选后,都会触发selection-change事件,其参数为当前被勾选数据集合。
需要考虑的问题点大致有:
- 1.由于翻页、查询等操作,数据被刷新后,勾选状态会消失,需要防止重复选择
- 2.翻页后进行勾选,之前页面已勾选的数据不会存在与selection-change的参数中,得想办法保留
- 3.取消勾选时,selection-change的参数不会暂时取消了什么,只会展示已勾选数据,得想办法判断哪些数据被取消了。
对于这些问题,我的解决思路是:
- 1.定义两个变量:
- 1.1“当前选择”集合,用来记录当前查询结果的勾选
- 1.2.“所有选择”集合,用来记录所有页面的勾选结果
- 2.每次查询结束后,对本次查询结果中已被勾选的数据进行默认勾选,并将勾选数据放入“当前选择”集合
- 3.用户操作勾选时,@selection-change的结果与“当前选择”进行比较,来决定如何操作“所有选择”集合
进一步的实现思路,我以注释形式写在了下文的代码中。
HTML部分
在element的Table中,每一列是直接使用<el-table-column>定义的。代码如下:(在iview中是在js中定义)
<template>
<!-- 用户查询部分 -->
<Form inline @submit.native.prevent>
<FormItem label="姓名" :label-width="60">
<Input type="text" v-model="userQueryData.userName" style="width:200px"></Input>
</FormItem>
<FormItem>
<Button type="primary" @click="doUserQuery" html-type="submit">查询</Button>
</FormItem>
</Form>
<!-- table展示部分 -->
<el-table :data="userlist" ref="multipleTable" border @selection-change="changeFun">
<el-table-column type="selection"/>
<el-table-column prop="principal" label="用户账号"></el-table-column>
<el-table-column prop="userName" label="用户姓名"></el-table-column>
</el-table>
<!-- 分页功能 -->
<Page :current="usercurrent" :total="usertotal" show-sizer :page-size-opts="[10,20,30,40,50,100]" show-total
@on-change="userPageChange" @on-page-size-change="userPageSizeChange"></Page>
<!-- 选择完成按钮 -->
<div style="margin-top: 20px">
<Button @click="doConfirm">确定</Button>
</div>
</template>
JS部分
userlist的查询结果数据结构如下:
userlist:[{"userId":1,"principal":"DEMO1","userName":"用户1"},
{"userId":2,"principal":"DEMO2","userName":"用户2"}
{"userId":3,"principal":"DEMO3","userName":"用户3"}]
JS的具体代码如下:
<script>
import {alllist} from '@/api/info/tUserInfo'
export default {
data(){
return {
userlist:[],
usercurrent: 1,
usertotal: 0,
userQueryData:{
page:1,
pageSize: 10,
userName: null
},
selectCurrent:[],
selectAll:[],
selectFlag:true
},
methods: {
//翻页时,修改查询参数
userPageChange(val){
this.userQueryData.page = val
this.userFetchData()
},
userPageSizeChange (val) {
this.userQueryData.pageSize = val
this.userFetchData()
},
doUserQuery(){
this.userQueryData.page = 1
this.userFetchData()
},
//查询时,做同步处理,等待返回查询结果后再进行后续操作
async userFetchData(){
//此处使用flag,是为了和页面上勾选时做区分
//因为查询完毕时,会对将已选择的数据勾选上,使用(this.$refs.multipleTable.toggleRowSelection(row);)这个方法进行勾选时,也会触发@selection-change
this.selectFlag = false;
this.selectCurrent = [];
await alllist(this.userQueryData).then(({data})=>{
this.userlist = data.records
this.usercurrent = data.current
this.usertotal = data.total
})
this.tickUserChoosed();
this.selectFlag = true;
},
//将已选择的数据,展示为已勾选,并加入当前选择数据中
tickUserChoosed(){
this.userlist.forEach(row => {
if(this.include(this.selectAll,row)){
this.$refs.multipleTable.toggleRowSelection(row);
let selectEnty ={
userId:row.userId,
userName:row.userName
}
this.selectCurrent.push(selectEnty)
}
})
},
//判断一个数据,是否包含于数组中。
//因为数组中存的是多个键值对,无法使用js自带函数判断,得手动写逻辑,选出主键进行比较
include(select,item){
let flag = false;
select.forEach((enty,i)=>{
if(enty.userId == item.userId){
flag = true;
return;
}
})
return flag;
},
//@selection-change触发时的操作
changeFun(val) {
if(this.selectFlag){
//如果当前的选择,不在新选择里,则移出选择
this.selectCurrent.forEach(selectOld=>{
if(!this.include(val,selectOld)&&this.include(this.selectAll,selectOld)){
this.selectAll.forEach((enty,i)=>{
if(enty.userId == selectOld.userId){
this.selectAll.splice(i,1)
}
})
}
})
//如果新的选择,不在选择里,则加入选择
val.forEach(selectNew=>{
let selectEnty ={
userId:selectNew.userId,
userName:selectNew.userName
}
if(!this.include(this.selectAll,selectEnty)){
this.selectAll.push(selectEnty)
}
})
//复制给当前选择
this.selectCurrent = JSON.parse(JSON.stringify(val));
}
},
//选择完毕后的操作,具体操作省略,选择的最终结果都在this.selectAll中,对其操作即可
doConfirm(){}
}
本文探讨了在使用Element UI的Table组件进行数据展示并需要分页多选时的实现方法。通过分析难点,如数据刷新后的勾选状态丢失、翻页后的选择跟踪等问题,提出了一种解决方案。在HTML部分,展示了如何定义Table列;在JS部分,详细解释了如何处理查询结果和用户选择,以维护多选状态。

3335

被折叠的 条评论
为什么被折叠?



