目录

为什么要封装分页组件?

分页组件的封装

如何使用?

为什么要封装分页组件?

分页组件用的最多的就是和表格一起,构成表格数据的翻页显示,当然也不仅限于表格,例如其它的流式加载、图片分批次加载等,都会用到分页组件。

这里以表格为例,通常我们写一个分页展示的表格,都会写一个<el-table></el-table>,然后在下面再写一个<el-pagination></el-pagination>的分页组件,分页组件里面有很多参数和触发函数,比如::page-sizes :total :current-page :page-size 及 layout等,触发函数一般有 @current-change @size-change 等,而以上的参数和触发函数对于一个项目中用到的所有分页组件几乎都是一样的,如果我们每写一个翻页表格,再写一个分页组件,这样就会显得很啰嗦,重复代码多。

这里,我们把<el-pagination>组件进一步封装成<XxPagination>,引入前端工程中,再写翻页表格时,只需引入<XxPagination>或有按需求传入自己的参数,不需要写重复的参数和触发函数。

分页组件的封装

这个分页组件是我同事封装的,简单、易用。用到了 Vue.js 2.2.0 版本后新增的 API provide/inject,来进行父子组件之间的参数传递。它的特性是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。这种方式可以避免在使用props传值时,必须将每一个属性都传递给子组件的写法,当使用的公共组件不确定会被传递什么值的时候,使用这种写法非常方便。

此外,我们还用到了vue中的mixinsmixins就是定义一部分公共的方法或者计算属性,然后混入到各个组件中使用,方便管理与统一修改。若有不理解的可以百度了解一下哦。

首先,按照上一篇vue element-ui之怎么封装一个自己的组件中的方法,我们在components下创建一个xx-pagination文件夹,然后在下面创建一个index.vue,代码如下:

<template>
  <el-pagination
    @current-change="onPageChange"
    @size-change="onPageSizeChange"
    :page-sizes="[10, 20, 50, 100]"
    :total="iTotal"
    :current-page="iCurrentPage"
    :page-size="iPageSize"
    layout="total, sizes, prev, pager, next, jumper"
  ></el-pagination>
</template>
<script>
export default {
  name: 'XxPagination', // 组件名
  inject: ['pagination'], // 接收后面mixins中provider的提供的参数
  props: {
    total: { // 总页数
      type: Number,
      default: 0
    },
    currentPage: { // 当前页
      type: Number,
      default: 1
    },
    pageSize: { // 每页显示条数
      type: Number,
      default: 10 // 默认10条
    }
  },
  watch: {
    pagination: { // 监听器
      deep: true,
      handler(v) {
        if (!v) {
          return
        }
        const { pageSize, total, currentPage } = v
        this.iPageSize = pageSize
        this.iTotal = total
        this.iCurrentPage = currentPage
      }
    }
  },
  data() {
    return {
      iPageSize: this.pageSize,
      iCurrentPage: this.currentPage,
      iTotal: this.total
    }
  },
  methods: {
    _emitPaginationChangeInfo() { // 触发父组件中特定的pageChanged函数
      const pageInfo = {
        pageSize: this.iPageSize,
        currentPage: this.iCurrentPage
      }
      this.$emit('pageChanged', pageInfo)
    },
    onPageSizeChange(pageSize) { // 每页条数改变函数
      const willMakePageChange = this.total / pageSize + 1 < this.iCurrentPage
      this.iPageSize = pageSize
      // 可能会造成页码改变发生,这时候不发送事件,因为可能造成事件死循环
      if (!willMakePageChange) {
        this._emitPaginationChangeInfo()
      }
    },
    onPageChange(currentPage) { // 页码改变函数
      this.iCurrentPage = currentPage
      this._emitPaginationChangeInfo()
    }
  }
}
</script>

inject: ['pagination']   接收mixins的provider提供的参数值。

props: total总数, currentPage当前页码,pageSize每页显示条数。

watch:监听'pagination' 参数的改变,pagination是个对象,包含pageSize, total, currentPage

methods:_emitPaginationChangeInfo()函数会触发父组件中的pageChanged()函数,因此在使用XxPagination的父组件中要求自定义一个pageChanged()函数并自己实现触发后的相关逻辑。onPageSizeChange(pageSize)页面显示条数改变触发函数。onPageChange(currentPage)页码改变触发函数。

好了,接下来就是我们的mixins。在项目中创建一个js文件,我这里命名为PageMixins.js,具体代码如下:

import _ from 'lodash'

export default {
  provide() { // 这里定义provide 传递参数
    return {
      data: this.data || {}, // 表格数据
      pagination: this.pagination // 分页属性
    }
  },
  data() {
    return {
      data: [],
      pagination: {
        currentPage: 1,
        total: 0,
        pageSize: 10
      }
    }
  },
  methods: {
    onGotPageData({ content, totalElements, size, number }) {
      this.data = content
      this.pagination.currentPage = number + 1
      this.pagination.pageSize = size
      this.pagination.total = totalElements
    },
    onPageChanged({ currentPage, pageSize }) {
      this.pagination.currentPage = currentPage
      this.pagination.pageSize = pageSize
      if (this.getData) {
        this.getData()
      }
    },
    addPageInfo(params = {}) {
      Object.assign(params, {
        pageSize: this.pagination.pageSize,
        pageNumber: this.pagination.currentPage - 1
      })
      return params
    }
  }
}

provide:这里定义的就是上面inject接收的参数。

methods:addPageInfo()函数,把请求后台的参数传递进来,然后加上分页参数,包装成一个对象返回;onGotPageData()函数,在页面返回数据后调用,给分页组件设置后台返回的值。onPageChanged()函数,页码改变触发,然后调用父组件的getData()函数。

如何使用?

<template>
  <!-- 就这么写一下可以了,这里会自动绑定分页数据以及触发数据请求 -->
  <XxPagination @pageChanged="onPageChanged"></XxPagination>
</template>

<script>
import PageMixins from '@/pages/common/mixins/PageMixins'

export default {
  mixins: [PageMixins],
  methods: {
    // 页面改变时,会主动掉头getData,因此必须定义getData函数,
    async getData() {
      // 为params上加入分页参数
      const params={}
      const data = await getAll(this.addPageInfo(params))
      // 处理分页数据
      this.onGotPageData(data)
    }
  },
}
</script>

上面讲解的可能不太明白,额,估计也很难说明白,但细心的你仔细读一下代码就能理解了。后续我会把这些组件的一些例子上传到github,等我有空吧哈哈哈。

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐