这篇是《基于element-ui table中多选框分页时的选择状态管理(一)》的优化版,大致需求就是
实现用户在不同pageIndex中对table进行操作之后,只需点击一次确定按钮就能提交用户的每一个操作项
,想了解具体需求可以查看第一版。
说得可能有点抽象,大家可以看一下下面这个图,用户在没提交的情况下可以在多个pageIndex中进行选择,点击确定
按钮,提交所有pageIndex中操作过的选项(包括:1. 原来选中但提交时取消选中的,2. 原来未选中但提交时选中的
)
1. 原因
虽然第一种方案也实现了产品的需求,但是我采取了禁用checkbox,只允许用户点击该行中除了checkbox以外的区域来实现对该行的选择,有点曲线救国的意思。
还有一个原因就是,需求代码虽然已经合进master并放到线上了,但是,自己这种做法还是被我们技术经理约谈了,约谈了,约谈了…
于是,打工人重开分支,开始优化…
2. 思路
这一回肯定是不能禁用checkBox了,那我们就合理利用elementUI官方给出的multipleSelection
属性吧,这里再花点时间解释一下这个属性:
multipleSelection是一个数组,表示table中当前pageIndex的所有选中项,我们每选中一项,multipleSelection中就会push进我们刚选中的项,而我们每取消一项,multipleSelection就会删除我们取消的那一项
第二版我是这样设计的:
具体思路请看代码实现
3. 代码
template代码
<template>
<div>
<el-dialog width="900px" :visible="visible" title="公司权限" @close="updateVsible(false)">
<el-table
ref="multipleTable"
:data="list"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column
type="selection"
width="55"
/>
<el-table-column
prop="liveCompanyName"
label="公司名"
/>
</el-table>
<el-pagination
v-if="totalCount"
:disabled="loading.list"
:class="'db-pagination-size-' + pageSize"
style="margin-top: 20px;"
background
layout="total, prev, pager, next"
:current-page="pageIndex"
:page-size="pageSize"
:total="totalCount"
@current-change="fetchList"
/>
<span slot="footer">
<el-button type="primary" @click="handleCreateClick">
确定
</el-button>
<el-button @click="updateVsible(false)">
取消
</el-button>
</span>
</el-dialog>
</div>
</template>
script功能代码:
<script>
export default {
name: 'CompanyEditor',
props: {
visible: {
type: Boolean,
default: false
}
},
data() {
return {
list: [],
multipleSelection: [],
totalCount: 0,
pageIndex: 1,
pageSize: 20,
/** 临时改变的所有选中项 */
changeListMap: new Map(),
/** 接口返回的所有页面的数据 */
allListMap: new Map()
}
},
watch: {
visible(newVal) {
if (newVal) {
this.initModal()
}
},
/** 监听选中项的改变更新changListMap */
multipleSelection(newVal) {
this.changeListMap.set(this.pageIndex, newVal)
}
},
methods: {
initModal() {
this.initParams()
this.fetchList()
},
initParams() {
this.pageIndex = 1
this.list = []
this.totalCount = 0
},
/**
* 获取公司列表
*/
async fetchList(pageIndex = this.pageIndex) {
// 已经请求过的页面取allListMap中的数据,无需再次请求
if (this.allListMap.get(pageIndex)) {
this.fetchLocalList(pageIndex)
return
}
// 这里请求接口得到响应数据res
if (res?.success && res?.data?.list) {
const { totalCount = 0, pageIndex, list = [] } = res.data
this.list = list
this.totalCount = totalCount
this.pageIndex = pageIndex
// 新获取的数据更新到allListMap
this.allListMap.set(pageIndex, list)
// 更新选中项
this.$nextTick(() => {
this.list.forEach(item => {
this.$refs.multipleTable.toggleRowSelection(item, item.hasPermission)
})
})
}
},
/** 获取map中的数据 */
fetchLocalList(pageIndex = this.pageIndex) {
// 取出当前页的数据
this.list = this.allListMap.get(pageIndex)
this.pageIndex = pageIndex
// 取出当前页的选中项
const currentList = this.changeListMap.get(pageIndex)
// 更新选中项
this.$nextTick(() => {
currentList.forEach(el => {
this.$refs.multipleTable.toggleRowSelection(el, true)
})
})
},
async handleCreateClick() {
const { adminId, allListMap, changeListMap } = this
const newAllListMap = [...allListMap.values()].flat()
const newChangeListMap = [...changeListMap.values()].flat()
const upList = []
// 添加所有选中项到upList
newChangeListMap.forEach(item => {
upList.push({ liveCompanyId: item.liveCompanyId, hasPermission: true })
})
// 添加原本选中但取消选中的项到upList
newAllListMap.forEach(el => {
const { liveCompanyId, hasPermission } = el
if (hasPermission) {
const exist = newChangeListMap.findIndex(item => item.liveCompanyId === liveCompanyId) >= 0
if (exist) return
upList.push({ liveCompanyId, hasPermission: !hasPermission })
}
})
// 请求接口提交upList
// ...
},
// 提交或者取消,初始化两个map,关闭弹窗
// 这里根据自己的实际业务,没有弹窗的可以不用关闭
updateVsible(visible) {
this.changeListMap = new Map()
this.allListMap = new Map()
this.$emit('update:visible', visible)
},
// 改变已选项列表
handleSelectionChange(val, index) {
this.multipleSelection = val
},
// 点击改变当前项选中状态
handleRowClick(val) {
const { multipleSelection } = this
const { liveCompanyId } = val
const exist = multipleSelection.findIndex(item => item.liveCompanyId === liveCompanyId) >= 0
this.$refs.multipleTable.toggleRowSelection(val, !exist)
}
}
}
</script>
基本不需要style代码
4. 实现效果
- 初始化第一页数据,点击提交查看效果
- changListMap有1项,选中1项
- allListMap有1项,包含20条
- 提交包含1项,其状态为true
- 在第一页增加一个选中项,点击提交查看效果
- changListMap有1项,选中2项
- allListMap有1项,包含20条
- 提交包含2项,状态为2true
- 在第一页取消原本的选中项,点击提交查看效果
- changListMap有1项,选中1项
- allListMap有1项,包含20条
- 提交包含2项,状态为1true 1false
- 切换到第二页,点击提交查看效果
- changListMap有2项,每项各选中一个
- allListMap有2项,每项各20条
- 提交包含3项,状态为2true 1false (第一页新增一个,取消一个默认,第二页一个默认)
- 在第二页,新增两个选项,点击提交查看效果
- changListMap有2项,第一项选中1,第二项选中3
- allListMap有2项,每项各20条
- 提交包含3项,状态为4true 1false (第一页新增一个,取消一个默认,第二页一个默认,新增两个)
- 在第二页取消一个新增项,点击提交查看效果
- changListMap有2项,第一项选中1,第二项选中2
- allListMap有2项,每项各20条
- 提交包含3项,状态为3true 1false (第一页新增一个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
- 返回第一页,点击提交查看效果
- changListMap有2项,第一项选中1,第二项选中2
- allListMap有2项,每项各20条
- 提交包含3项,状态为3true 1false (第一页新增一个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
- 最后,在第一页再新增一项,点击提交查看效果
- changListMap有2项,第一项选中2,第二项选中2
- allListMap有2项,每项各20条
- 提交包含3项,状态为4true 1false (第一页新增两个,取消一个默认,第二页一个默认,一个新增,原本新增的被取消)
5.总结
从上面的效果图可以看出,我们最后只要提交upList中的数据给后端就行,既实现了记住每页的操作记录,也减少了接口请求,比第一版提交的数据也少了不少,对性能优化还是起到了一些微乎其微的作用,哈哈
虽然这一版相对于第一版确实优化了不少,但是可能还有更好的解决办法,或者我这第二版还能继续优化,如果小伙伴们有更好的办法,欢迎再评论区留言噢。。。
end~~
鉴于笔者水平有限,若本文存在不当之处欢迎指出噢
有疑问的小伙伴,欢迎在下方留言,笔者看到都会回复的
若未能及时回答,也可以选择加入前端应知应会交流群群提问噢~~
群号:216644014(前端应知应会)