Element Plus 分页组件的二次封装

107 阅读1分钟
<template>
  <div class="pagination-container" :class="`align-${align}`">
    <el-pagination
      v-bind="$attrs"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :background="background"
      :pager-count="pagerCount"
      :layout="layout"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup lang="ts">
defineOptions({ name: 'Pagination' })

const props = defineProps({
  /** 总条目数 */
  total: { type: Number, required: true },
  /** 当前页数 */
  page: { type: Number, default: 1 },
  /** 每页显示条目个数 */
  limit: { type: Number, default: 10 },
  /** 每页显示个数选择器的选项设置 */
  pageSizeList: { type: Array as PropType<number[]>, default: [10, 20, 30, 40, 50] },
  /** 组件布局,子组件名用逗号分隔 */
  layout: { type: String, default: 'total, sizes, prev, pager, next, jumper' },
  /** 是否为分页按钮添加背景色 */
  background: { type: Boolean, default: true },
  /** 移动端页码按钮的数量端默认值 5 */
  pagerCount: { type: Number, default: document.body.clientWidth < 992 ? 5 : 7 },
  /** 分页组件 左 中 右 */
  align: { type: String as PropType<'left' | 'center' | 'right'>, default: 'center' }
})

/** 接收父组件传递的事件 */
const emits = defineEmits(['update:page', 'update:limit', 'pagination'])

/** 利用 computed 拦截 v-model */
const currentPage = computed({
  get() {
    return props.page
  },
  set(value: number) {
    emits('update:page', value)
  }
})
const pageSize = computed({
  get() {
    return props.limit
  },
  set(value: number) {
    emits('update:limit', value)
  }
})

/** 处理当前页码数改变的操作 */
function handleCurrentChange(value: number) {
  emits('pagination')
}

/** page-size 改变时触发 */
function handleSizeChange(value: number) {
  if (currentPage.value * value > props.total) currentPage.value = 1
  emits('pagination')
}
</script>

<style lang="scss" scoped>
.pagination-container {
  display: flex;
  align-items: center;
  margin-top: 16px;
}
.align-left {
  justify-content: flex-start;
}
.align-center {
  justify-content: center;
}
.align-right {
  justify-content: flex-end;
}
</style>