基于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
  })
}

原文地址:https://www.cnblogs.com/Juliana1992/p/10456442.html

时间: 2024-11-05 18:39:29

基于Vue的简单通用分页组件的相关文章

基于Vue.js的表格分页组件

BootPage组件简介 其实也不是啥高大上的组件了,相反确实一个简单的表格分页组件而已,主要是自己最近项目中需要一个表格分页组件,而Vue官方组件库里分页组件都功能太强大或者没有适合我的,所以就自己写了一个凑合着用,或许有人和我一样需要这样一个简单的分页组件来实现简单的分页功能,我便在这里分享一下,大家自觉填坑咯. 如需高大上的组件,可以移步Vue官方组件库:https://github.com/vuejs/awesome-vue#libraries--plugins BootPage是一款支

Vue.js的表格分页组件

转自:http://www.cnblogs.com/Leo_wl/p/5522299.html 有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫BootPage. 不了解Vue.js的童鞋可以移步我的上一篇文章<浅谈Vue.js>了解一下. BootPage组件简介 其实也不是啥高大上的组件了,相反确实一个简单的表格分页组件而已,主要是自己最近项目中需要一个表格分页组件,而Vue官方组件

ReactJS实现的通用分页组件

大家多少都自己写过各种版本的分页工具条吧,像纯服务版的,纯jsWeb板的,Angular版的,因为这个基础得不能再基础的功能太多地方都会用到,下面我给出以个用ReactJS实现的版本,首先上图看下效果:    注意这个组件需要ES6环境,最好使用NodeJS结合Webpack来打包:webpack --display-error-details --config webpack.config.js 此React版分页组件请亲们结合redux来使用比较方便,UI = Fn(State)    基本

vue-awesome-swipe 基于vue使用的轮播组件 使用

npm install vue-awesome-swiper --save  //基于vue使用的轮播组件 <template> <swiper :options="swiperOption" ref="mySwiper"> <swiper-slide v-for="(banner,index) in banners" :key="index"> <img v-if="ban

vue+element UI实现分页组件

1.前言 在web页面中,常常需要将后台查询到的数据以表格形式展示出来,而这些数据量往往会非常庞大,如果将所有要展示的数据一次性请求获取并展示到页面上,那页面长度势必会变得非常的长,很不美观.更重要的是,如果数据量过于大,在页面加载时一次性请求全部数据将会耗费大量网络资源,性能极低.但是,如果我们可以将数据分页展示,这样页面首先不会变的冗长,另外只有用户点击页码才会发出请求并且每次请求的数据量也不会很大,这就极大的节省了网络资源,提高了性能.本文就以vue结合element UI实现一个数据分页

vue2-org-tree 基于VUE的部门组织架构组件,增删节点实现

本文所用组件传送门:vue-org-tree 本文基于antd (其他前端组件框架操作基本都类似的: iview,elementui,boostrap-vue...) 当然,github上还有其他类似的组件,实现方法各有不同,显示效果也有差异,但都是很方便的组件. 看到网上有很多相关的使用教程,github上也写得很清楚,这里恕不在重复,本文主要实现增删节点. 场景:我们通常展示部门树的时候,简单的直接就是一个下拉框展示,为了显示明显,可能会使用一些树.    图片截至:(antd vue文档)

基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多

通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无限滚动加载不需要写首次载入列表的函数, 代码如下: html: //父组件 <div v-infinite-scroll="loadMore" infinite-scroll-disabled="loading" infinite-scroll-distance=

asp.net MVC通用分页组件 使用方便 通用性强

该分页控件的显示逻辑: 1 当前页面反色突出显示,链接不可点击 2 第一页时首页链接不可点击 3 最后一页时尾页链接不可点击 4 当前页面左右各显示页码可以设置调节,如果左右一样则居中 5 当左边页码不足时,右侧补充 6 当右侧页面不足时左侧补充 7 总显示页码数为左侧+右侧+1(当前) 组成部分: 1 PageModel 便于向组件传递参数 public class PageModel { /// <summary> /// 数据总条数 /// </summary> public

Mint-ui(基于 Vue.js 的移动端组件库)的使用

官网: http://mint-ui.github.io/#!/zh-cn 1.安装包 npm install mint-ui -S 2.导包 import Vue from 'vue'import MintUi from 'mint-ui' // 导入全部组件import 'mint-ui/lib/style.css'Vue.use(MintUi) 3.css类mint-ui组建的使用 <template> <div>  <mt-button type="defa