分页组件是每一个系统里必不可少的一个组件,分页组件分为两部分。第一部分是模版部分,用于显示当前分页组件的状态,例如正在获取数据、没有数据、没有下一页等等;第二部分是分页数据对象,用于封装一个分页组件的属性和方法,例如获取数据的 url、当前第几页(page)、每次加载条数(count)、一共有多少页(totalPage)等等,方法可能会有上一页、下一页、处理数据等等。
分页数据对象
import base from '@/api/base' export default class Pagination { constructor({ url, processFunc, processExt, count = 10, isMock = false }) { // 数据访问地址 this.url = url // 数据集合 this.list = [] // 第几页 this.page = 1 // 一共几页 this.totalPage = 1 // 加载数据条数 this.count = count // 数据处理函数 this.processFunc = processFunc // 错误处理函数 this.processExt = processExt // 正在加载中 this.loading = false // 参数 this.params = {} // 是否底部 this.reachBottom = false // 是否为空 this.empty = true // 是否需要清除 this.toClear = false // 是否为mock数据 this.isMock = isMock } /** * 加载下一页数据 */ async next(args) { if (this.loading) { // console.warn('page loading!') return this } const param = { pageNo: this.page, pageSize: this.count } // 附加参数 this.loading = true try { Object.assign(param, args) let res let data try { res = await base.get(this.url, param) data = res.data } catch (e) { if (typeof this.processExt === 'function') { data = this.processExt(e) } else { throw new Error(e) } } // 底部判断 if (data === null || data.length < 1) { if (this.toClear) { this.clear() } else { this.reachBottom = true } return this } this.empty = false // 处理数据 this._processData(data) // 设置数据 if (this.toClear) { this.list = data this.toClear = false } else { this.list = this.list.concat(data) } ++this.page this.totalPage = res.page.totalPages if ( (res.page && res.page.page === res.page.totalPages) || data.length < this.count ) { this.reachBottom = true } return this } finally { this.loading = false } } /** * 恢复到第一页 */ reset() { this.empty = true this.toClear = true this.page = 1 this.reachBottom = false } clear() { this.toClear = false this.page = 1 this.list = [] } /** * 处理数据(私有) */ _processData(data) { if (this.processFunc) { for (let i in data) { const result = this.processFunc(data[i]) if (result) { data[i] = result } } } } }
分页模版
<template> <div class="z-page-stat"> <p v-show="page.loading" class="page-loading"> <span class="ign-loading"></span> </p> <div class="u-more-btn" v-show="showLoadMore && !page.reachBottom && !page.loading && !page.empty" @click="$emit('nextPage')" > <span>查看更多</span> </div> <p class="reach-btm" v-show="showBtmTx && !page.empty && page.reachBottom"> 到底了~ </p> <div class="page-empty" v-show="!page.loading && page.empty"> <div class="empty-inner"> <div class="img-bg" v-if="emptyImg"> <img v-if="!emptyImg || emptyImg == 1" src="../../img/empty-page.png" alt="" /> </div> <p class="tx">{{emptyText}}</p> <div class="empty-ctn"> <slot name="empty"></slot> </div> </div> </div> <slot name="other"></slot> </div> </template> <script> export default { name: 'pageStatus', data() { return {} }, props: { page: {}, emptyImg: {}, emptyText: { type: String, default: '暂时没有数据' }, showLoadMore: { // 是否显示加载更多按钮 type: Boolean, default: false }, showBtmTx: { // 到底了文字要不要显示 type: Boolean, default: true } }, components: {}, created: function() {}, mounted: function() {}, methods: {} } </script> <style lang="stylus" rel="stylesheet/stylus"> .z-page-stat text-align center letter-spacing 2px color #757575 line-height 60px .page-loading .ign-loading border-radius 100% margin 16px 0 animation-fill-mode both border 2px solid #e8473f /* no */ border-bottom-color transparent height 25px /* no */ width 25px /* no */ background transparent !important display inline-block animation rotate 1s 0s linear infinite .page-empty position absolute left 0 width 100% top 50% transform translate(0, -50%) .empty-inner width 320px margin 0 auto .img-bg position relative display inline-block width 254px height 254px background #d6d6d6 border-radius 50% margin-bottom 20px img width 94px margin-top 28px .tx color #8c8c8c .empty-ctn .u-btn margin-top 90px margin-left 20px border 2px solid #464646 /* no */ box-shadow none width 168px height 62px line-height 62px </style>
使用组件
<template> <div> <div class="card-content" v-for="act in page.list" :key="act.id"> <p> {{act.title}} </p> </div> <p-status :page="page"></p-status> </div> </template> <script> import { mainList } from '@/api/activity' import PageStatus from 'comps/pageStatus.vue' export default { data() { return { page: mainList() } }, mixins: [appPage], computed: {}, created: async function() { this.page.next({ /*传参*/ }) }, components: { 'p-status': PageStatus } } </script>
// @/api/activity import Pagination from '@/utils/Pagination' /** * 列表 */ export function mainList() { const url = `/activity/activity/list.do` return new Pagination({ url: url }) }
来源:https://www.cnblogs.com/Juliana1992/p/10456442.html