Skip to content

分页组件的封装

TIP

这个分页组件只是一个封装,具体实现请自行实现。

CustomPagination.vue 组件

vue
<template>
  <div v-if="isPaginationVisible" class="custom-pagination">
    <el-pagination
      :current-page="innerCurrentPage"
      :page-size="innerPageSize"
      :total="total"
      :layout="layout"
      :page-sizes="pageSizes"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';

// 定义 props
const props = defineProps({
  // 总数据量
  total: {
    type: Number,
    required: true
  },
  // 每页显示数量
  pageSize: {
    type: Number,
    default: 10
  },
  // 当前页码
  currentPage: {
    type: Number,
    default: 1
  },
  // 分页布局
  layout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  // 页大小选项
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 50, 100]
  },
  // 是否显示分页
  showPagination: {
    type: Boolean,
    default: true
  },
  // 分页大小变化时的回调
  onSizeChange: {
    type: Function,
    default: null
  },
  // 分页页码变化时的回调
  onPageChange: {
    type: Function,
    default: null
  }
});

// 定义 emits
const emit = defineEmits(['update:currentPage', 'update:pageSize']);

// 内部页码状态
const innerCurrentPage = ref(props.currentPage);
// 内部页大小状态
const innerPageSize = ref(props.pageSize);

// 监听外部 currentPage 变化
watch(() => props.currentPage, (newPage) => {
  if (newPage !== innerCurrentPage.value) {
    innerCurrentPage.value = newPage;
  }
});

// 监听外部 pageSize 变化
watch(() => props.pageSize, (newSize) => {
  if (newSize !== innerPageSize.value) {
    innerPageSize.value = newSize;
    // 页大小变化时重置到第一页
    innerCurrentPage.value = 1;
  }
});

// 处理分页大小变化
const handleSizeChange = (size) => {
  innerPageSize.value = size;
  innerCurrentPage.value = 1;
  emit('update:pageSize', size);
  if (props.onSizeChange) {
    props.onSizeChange(size);
  }
};

// 处理分页页码变化
const handleCurrentChange = (page) => {
  innerCurrentPage.value = page;
  emit('update:currentPage', page);
  if (props.onPageChange) {
    props.onPageChange(page);
  }
};

// 计算分页是否可见
const isPaginationVisible = computed(() => {
  return props.showPagination && props.total > 0;
});
</script>

<style scoped>
.custom-pagination {
  margin-top: 15px;
  display: flex;
  justify-content: flex-end;
}
</style>
<template>
  <div v-if="isPaginationVisible" class="custom-pagination">
    <el-pagination
      :current-page="innerCurrentPage"
      :page-size="innerPageSize"
      :total="total"
      :layout="layout"
      :page-sizes="pageSizes"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';

// 定义 props
const props = defineProps({
  // 总数据量
  total: {
    type: Number,
    required: true
  },
  // 每页显示数量
  pageSize: {
    type: Number,
    default: 10
  },
  // 当前页码
  currentPage: {
    type: Number,
    default: 1
  },
  // 分页布局
  layout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  // 页大小选项
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 50, 100]
  },
  // 是否显示分页
  showPagination: {
    type: Boolean,
    default: true
  },
  // 分页大小变化时的回调
  onSizeChange: {
    type: Function,
    default: null
  },
  // 分页页码变化时的回调
  onPageChange: {
    type: Function,
    default: null
  }
});

// 定义 emits
const emit = defineEmits(['update:currentPage', 'update:pageSize']);

// 内部页码状态
const innerCurrentPage = ref(props.currentPage);
// 内部页大小状态
const innerPageSize = ref(props.pageSize);

// 监听外部 currentPage 变化
watch(() => props.currentPage, (newPage) => {
  if (newPage !== innerCurrentPage.value) {
    innerCurrentPage.value = newPage;
  }
});

// 监听外部 pageSize 变化
watch(() => props.pageSize, (newSize) => {
  if (newSize !== innerPageSize.value) {
    innerPageSize.value = newSize;
    // 页大小变化时重置到第一页
    innerCurrentPage.value = 1;
  }
});

// 处理分页大小变化
const handleSizeChange = (size) => {
  innerPageSize.value = size;
  innerCurrentPage.value = 1;
  emit('update:pageSize', size);
  if (props.onSizeChange) {
    props.onSizeChange(size);
  }
};

// 处理分页页码变化
const handleCurrentChange = (page) => {
  innerCurrentPage.value = page;
  emit('update:currentPage', page);
  if (props.onPageChange) {
    props.onPageChange(page);
  }
};

// 计算分页是否可见
const isPaginationVisible = computed(() => {
  return props.showPagination && props.total > 0;
});
</script>

<style scoped>
.custom-pagination {
  margin-top: 15px;
  display: flex;
  justify-content: flex-end;
}
</style>

页面调用

vue
<template>
  <div class="table-demo">
    <CustomTable
      :data="tableData"
      :columns="columns"
      border
      stripe
      highlight-current-row
      selection
      show-index
      :operationOptions="operationOptions"
      :paginationConfig="paginationConfig"
    />
    
    <CustomPagination
      v-model:currentPage="paginationConfig.currentPage"
      v-model:pageSize="paginationConfig.pageSize"
      :total="tableData.length"
      :pageSizes="[5, 10, 15, 20]"
      @update:currentPage="fetchData"
      @update:pageSize="fetchData"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import CustomTable from '@/components/CustomTable.vue';
import CustomPagination from '@/components/CustomPagination.vue';

const tableData = ref([
  // 表格数据...
]);

const columns = ref([
  // 表格列配置...
]);

const operationOptions = ref([
  // 操作选项...
]);

const paginationConfig = ref({
  currentPage: 1,
  pageSize: 5
});

// 模拟数据加载
const fetchData = () => {
  console.log('加载数据', paginationConfig.value);
  // 这里可以添加实际的数据加载逻辑
};
</script>
<template>
  <div class="table-demo">
    <CustomTable
      :data="tableData"
      :columns="columns"
      border
      stripe
      highlight-current-row
      selection
      show-index
      :operationOptions="operationOptions"
      :paginationConfig="paginationConfig"
    />
    
    <CustomPagination
      v-model:currentPage="paginationConfig.currentPage"
      v-model:pageSize="paginationConfig.pageSize"
      :total="tableData.length"
      :pageSizes="[5, 10, 15, 20]"
      @update:currentPage="fetchData"
      @update:pageSize="fetchData"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import CustomTable from '@/components/CustomTable.vue';
import CustomPagination from '@/components/CustomPagination.vue';

const tableData = ref([
  // 表格数据...
]);

const columns = ref([
  // 表格列配置...
]);

const operationOptions = ref([
  // 操作选项...
]);

const paginationConfig = ref({
  currentPage: 1,
  pageSize: 5
});

// 模拟数据加载
const fetchData = () => {
  console.log('加载数据', paginationConfig.value);
  // 这里可以添加实际的数据加载逻辑
};
</script>

程序员小洛文档