使用场景:做页面时遇到后端接口不支持分页,接口一次性返回表格所有数据,而产品要求前端不能一次性展示,需要有分页功能。
配合mdesign库的md-pagination组件,最终实现的效果如下
步骤:
一、封装分页hook,创建useUserPagination.ts
import { Ref, computed, ref, watch } from 'vue';
export const useUserPagination = <T>(database: Ref<T[]>, pageSize = 10) => {
// 声明一个data变量,用于存储分页后的数据
const data = ref<T[]>([]);
// 声明一个changeData函数,用于分页
function changeData({ currentPage, currentPageSize }: { currentPage: number; currentPageSize: number }) {
// 计算当前页面的起始位置
const start = (currentPage - 1) * currentPageSize;
// 计算当前页面的结束位置
const end = start + currentPageSize;
// 获取当前页面的数据
const dataSliced = database.value.slice(start, end);
data.value = dataSliced;
return dataSliced;
}
const currentPage = ref(1);
const currentPageSize = ref(pageSize);
const total = computed(() => database.value.length);
const pageCount = computed(() => Math.ceil(total.value / currentPageSize.value));
// 监听database变量,当database变量发生变化时,触发sliceData函数,实现分页
watch([database, currentPage], () => {
changeData({ currentPage: currentPage.value, currentPageSize: currentPageSize.value });
});
// 返回分页后的数据和控制器的数据
return {
currentPage,
currentPageSize,
total,
pageCount,
data,
goto(val:string|number) {
currentPage.value = +val;
},
};
};
二、页面的分页组件md-pagination中使用
<template>
....
<template v-slot:footer>
<div class="dialog-footer">
<md-pagination
small
background
layout="total, prev, pager, next"
:current-page="pagination.currentPage.value"
:page-size="pagination.currentPageSize.value"
:total="pagination.total.value|| 0"
@current-change="changePage"
/>
...
</div>
</template>
</template>
<script setup>
import { useUserPagination } from '../../../../../composition/useUserPagination';
//这里省略了接口获取tableData
const pagination = useUserPagination(tableData, 10);
/** 详细地址都加上四级地址 */
const joinAddress = (province, city, district, town, detailAddr) => {
return (province || '') + (city || '') + (district || '') + (town || '') + (detailAddr || '');
};
const changePage = (val) => {
pagination.goto(+val);
};
{
tableData.value = [];
info.value = {};
dialogFormVisible.value = false;
};
</script>
<style lang="less">
.items-info-content {
padding: 0 10px;
.title-info {
margin-bottom: 10px;
.title {
width: 70px;
margin-right: 5px;
}
}
.message-panel {
flex: 1;
color: var(--main-color);
> span {
margin-right: 10px;
}
}
}
.table-list{
height: 400px;
overflow: auto;
}
.dialog-footer {
display: flex;
flex-direction: row;
align-content: flex-end;
justify-content: flex-end;
align-items: center;
flex-wrap: nowrap;
.md-pagination{
margin-right: 20px;
}
}
</style>
~~