基于Vue的简单通用分页组件

vue

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

})

}

以上是 基于Vue的简单通用分页组件 的全部内容, 来源链接: utcz.com/z/378800.html

回到顶部