我们常见的分页勾选可以分为表格分页、非表格类分页, 其中要实现的就是 来回切换分页, 记住每一页选中的数据, 我看很多同学用了各种手段, 这里讲讲我认为比较简单的方案
表格分页勾选
实现表格类勾选记忆主要两种方案
方案一
利用表格插件自带记忆功能, 这里以 el-table 举例
<el-table :data="tableData" row-key="id" border ref="multipleTable" @selection-change="handleSelectionChange">
<el-table-column type="selection" :reserve-selection="true" width="55" />
<el-table-column label="通知标题" prop="messageName" />
<el-table-column label="发布时间" :formatter="formatTime" prop="publishTime" />
<el-table-column label="发布状态" prop="postStatus" />
<el-table-column label="操作" :width="200">...</el-table-column>
</el-table>
主要就是加这行代码 :reserve-selection="true" 然后在触发选中时赋值就OK了
handleSelectionChange(val) {
this.multipleSelection = val
}
这也是最简单的情况, 但是有些项目里用的表格插件不支持分页记忆, 但是它有其它功能需要用到那个插件不能换, 这个时候就需要我们手写表格分页记忆
方案二
<template>
<Table ref="multipleTable" :columns="columns" :data="data"></Table>
<Page :total="total" @on-change="onSearch"/>
</template>
<script>
//创建对象, 保存每一页勾选数据
const checkData = {}
export default {
methods: {
//分页时触发
onSearch(page) {
this.pageNo = page
checkData[page] = '当前页选中的数据'
//一般表格都能拿到, 实在不行自己在复选框选中时加个checked字段, 然后在这里过滤
this.getTableData()
},
getTableData() {
axios.get({
pageNo: this.pageNo,
pageSize: this.pageSize,
param: {
....
}
}).then(res => {
this.tableData = res.data
...
})
}
}
}
</script>
数据我们是保存了, 接下来就是取数据环节, 比如我们勾选之后,点击了导出数据按钮
<script>
export default {
...
methods: {
download() {
const ids = Object.values(checkData).flat()
//Object.values处理后=[Array(3), Array(2), Array(6)]
//需要flat扁平化下
httpRequest({ids})
}
}
}
</script>
分页数据是完成了, 但是表格勾选回显还要做下
<script>
export default {
...
methods: {
getTableData() {
axios.get({
pageNo: this.pageNo,
pageSize: this.pageSize,
param: {
....
}
}).then(res => {
this.tableData = res.data
//设置默认选中状态
const cureentPageSelectIds = checkData[this.pageNo]
this.tableData.map(row => {
cureentPageSelectIds.map(id => {
if (row.id === id) {
//说明之前勾选了, 重新选中它
this.$refs.multipleTable.selection(row)
}
})
})
})
}
}
}
</script>
就这样一个简单版的手写的分页记忆功能实现了 O(∩_∩)O ^_^
但是! 但是来了, 它还有个小问题就是当你分页过程中改变了每页数据量pageSize, 就得做一些特殊处理了, 想知道怎么处理吗, V me 50 肯德基 ^_^
卡片式分页记忆
除了上面的表格类比较常见的分页记忆还有如下图卡片类的, 这种就是手写 ul > li 做的
<template>
<div>
<ul>
<li v-for="item in cardList" :key="item.id">
<div class="card-top">
<el-checkbox v-model="item.checked"
:true-label="item.id"
:false-label="'false='+item.id"
@change="checkChange">
</el-checkbox>
<!-- true-label: 选中改的值, false-label: 没有选中的值-->
<span>{{ status }}</span>
</div>
<div class="card-content">...</div>
<li>
</ul>
<el-pagination :current-page="pageNo"
:page-size="pageSize"
@current-change="onSearch"
layout="prev, pager, next"
:total="total">
</el-pagination>
</div>
</template>
<script>
export default {
data() {
return {
pageNo: 1,
pageSize: 9,
total: 0,
cardList: [
//demo
// {
// id: 1,
// name: '西游记-1',
// url: '',
// checked: false,
// }
],
multipleSelection: [], //保存勾选数据
}
},
methods: {
checkChange(value) {
//没有选中时, 用false=区分, 可以自定义, 主要是为了区分取消勾选
if (value.startsWith('false=')) {
const ID = value.split('false=')[1]
this.multipleSelection.map((item, index, arr) => {
if (item.id === ID) {
//剔除取消勾选项
arr.splice(index, 1)
}
})
} else {
//选中时,追加勾选项
this.cardList.map(card => {
if (card.id === value) {
this.multipleSelection.push(card)
}
})
}
},
//以上就把勾选当前页完成了, 接下来搞下分页勾选记忆
async getCardList() {
this.cardList = ( await axios.get('url') ).data || []
this.cardList.forEach(card => {
this.multipleSelection.map(select => {
card.checked = (card.id === select.id) //增加选中字段
})
})
}
}
}
</script>
这样就完成卡片分页勾选记忆功能啦 (^▽^)
正如上面的截图, 还有个全选功能,我这里也写下
<template>
<el-checkbox v-model="checkAll" @change="handleCheckAll">全选</el-checkbox>
<Card />
<Page />
</template>
<script>
export default {
data() {
return {
...
checkAll: false
}
},
methods: {
handleCheckAll(value) {
if(value) { //全选
//所有选中的id 数组
const ids = this.multipleSelection.map(select => select.id)
//设置卡片数据checked
this.cardList.forEach(card => {
this.$set(card, 'checked', true)
//再更新下选中数组
if ( !ids.includes(card.id) ) {
//全选也只添加之前不存在的
this.multipleSelection.push(card)
}
})
} else { //全不选
this.cardList.forEach(card => {
this.$set(card, 'checked', false)
//把取消选中的剔除
this.multipleSelection.forEach((select, index, arr) => {
if(select.id === card.id) {
arr.splice(index, 1)
}
})
})
}
},
async getCardList() {
this.cardList = ( await axios.get('url') ).data || []
const CheckedIds = this.multipleSelection.map(item => item.id)
//这个方案比上面比上面双循环性能应该要好些
this.cardList.forEach(card => {
card.checked = CheckedIds.includes(card.id)
})
//增加了全选状态判断
this.checkAll = this.cardList.every(item => item.checked)
}
}
}
</script>
问题:
-
这里卡片分页为什么不用上面的表格分页手写记忆方案, 用对象保存每页勾选数据呢? 因为表格可以很轻松拿到当前页勾选数据, 而卡片的checkBox是我们手写的, 还不如用一个数组存全部勾选数据方便
-
为啥不直接监听cardList, 当前页可以, 分页了就不行了