分页组件是每一个系统里必不可少的一个组件,分页组件分为两部分。第一部分是模版部分,用于显示当前分页组件的状态,例如正在获取数据、没有数据、没有下一页等等;第二部分是分页数据对象,用于封装一个分页组件的属性和方法,例如获取数据的 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
})
}

最新文章

  1. NodeJS 学习总结 01 安装配置
  2. noip模拟赛 好元素 哈希表的第一题
  3. Bete冲刺第三阶段
  4. 6个原因说服你选择PostgreSQL9.6
  5. HashMap 和 HashTable区别
  6. ZOJ 1151 Word Reversal
  7. 阅读layim代码小记,实现可以更改用户签名的方法
  8. hadoop安装配置——伪分布模式
  9. 51nod1364 最大字典序排列
  10. 【英语】Bingo口语笔记(27) - 如何培养口语语感
  11. 使用导入导出进行备份和恢复OCR(10g)
  12. *[codility]Number-of-disc-intersections
  13. (转)IOS开发之——绘图(CGContext)
  14. iBatis查询结果部分为null的解决办法
  15. root用户不能修改iptable文件
  16. Oracle 11g RAC 自动应用PSU补丁简明版
  17. Docker 学习1 容器技术基础入门
  18. Linux下设置MySql自动启动
  19. Linux上的压缩与归档
  20. GridView中如何实现自定义时间货币等字符串格式?

热门文章

  1. Nodejs Redis 全部操作方法
  2. 谷歌浏览器安装POSTMAN
  3. Python 装饰器---装饰类的两种方法
  4. svn 查找指定文件和后缀变化
  5. 如何将freemarker文件转化为html文件
  6. iRedMail搭建完后登录提示【连接至IMAP服务器失败】(转)
  7. 视频直播时的QoS策略
  8. STM32F103 ucLinux开发BOOT
  9. Node学习笔记之模块实现
  10. MAC上安装GCC失败