分页这个功能可以说在开发管理系统中是必不可少的东西
为何分页?
答:因为数据量大,不可能全部给你展示,全部展示页面加载慢,且要不断下滑查看,体验差
谁做分页?
答:对于数据增长比较频繁的,比如订单列表通常后端来做这个分页;对于数据量增长缓慢数据量不大的,比如商品列表、分类列表、员工列表,前端来做分页是不错的选择
分页如何做?
答:
后端实现
通常后端提供一个接口,需要前端传入,页码,每页显示数据条数等参数,后端根据该参数分页查询返回数据。前端需要更新列表数据渲染,那么前端分页控件就只需要调用接口(动态传参),如图每个按钮绑定页码值等参数,点击则调用接口,如何知道有多少页?这个后端接口会做统计查询返回给前端的,前端计算:总数/每页展示数得到总页数,并进行渲染按钮
前端实现
后端会把所有数据全部返回,前端需要做的就是把全部数据列表做分割,按页展示,分页控件分页函数根据页码等参数截取列表的数据
实现这个通用分页控件:
我这里是基于el-pagination分页组件进行封装的一个精简版大家可以按需扩展。
需求:既能兼容后端分页,又可以在前端实现分页
1.自定义属性
如果是后端做分页的话,就传递count属性值这个属性代表总数据量,需要用来计算总页数
如果是前端做分页,就传递itemList属性值,这个属性表示总数据数组,根据这个数组的长度可以计算页数,根据页码可以对数组进行截取并把截取的单页数据通过自定义事件传递给父组件,父组件更新列表数据渲染
const props = defineProps({ itemList: {//数据列表 type: Array, default: null }, count: {//有值则分页功能后端实现 type: Number, default: null }, })
2.自定义事件
通过自定义事件可以把页码或者是分页后的数据传递给父组件
3.示例代码
分页控件完整代码:
<script lang="ts" setup> import { ref,onBeforeUpdate} from 'vue' const emit = defineEmits(['updateItemList']); // 接收父组件传递的数据() const props = defineProps({ itemList: {//数据列表 type: Array, default: null }, count: {//有值则分页功能后端实现 type: Number, default: null }, }) //--------------------------------------------------------数据分页------------------------------------------------------------------ const itemList = ref([])//待分页全部数据 const limitItemList = ref([])//分页后数据 const currentPage = ref(1); // 当前页码默认 const pageSize = ref(10); // 每页显示数量 //全部数据按每页展示数量、页码截取 const displayedItemList = () => { const startIndex = (currentPage.value - 1) * pageSize.value; const endIndex = startIndex + pageSize.value; limitItemList.value = itemList.value.slice(startIndex, endIndex); }; //选中页设置为当前页 function changePage(page:number) { currentPage.value = page } //------------------------------------------------------------------------------------------------------------------------------------ //预处理 onBeforeUpdate(() => { if (props.count != null&&props.itemList==null) { emit('updateItemList', currentPage.value) return } itemList.value = props.itemList displayedItemList() emit('updateItemList', limitItemList.value) }) </script> <template> <div style="display: flex;justify-content: center;margin-top: 10px;"> <el-pagination background="blue" layout="prev, pager, next" :total="props.count == null ? itemList.length : props.count" :current-page.sync="currentPage" :page-size="pageSize" @current-change="changePage" prev-text="上一页" next-text="下一页"> </el-pagination> </div> </template>
1.如果后端做分页
要传递总数据量,以及触发自定义事件(在该自定义事件的回调函数可以进行接口调用更新数据)
<div> <Limit :count="count" @updateItemList="getItemList"></Limit> </div>
//接收分页组件传递的页码 const getItemList = async (page:number) => { console.log('接收:') console.log(page) if (page != null) { loadingItemList.value = true //分页查询接口 const res = await orderListApi(activeName_order_status.value, page)//传递页码 orderList.value = res.data.data count.value = parseInt(res.data.count) } }
2.如果前端做分页
要传递所有数据的数组
<div> <Limit :itemList="itemList" @updateItemList="getLimitItemList" /> </div>
//接收分页组件分页后的每页数据 const getLimitItemList = (displayedItemList: Array<Object>) => { console.log("接收:") console.log(displayedItemList) limitItemList.value = displayedItemList }