use-pagination.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import type { Ref } from 'vue';
  2. import { computed, ref, unref } from 'vue';
  3. /**
  4. * Paginates an array of items
  5. * @param list The array to paginate
  6. * @param pageNo The current page number (1-based)
  7. * @param pageSize Number of items per page
  8. * @returns Paginated array slice
  9. * @throws {Error} If pageNo or pageSize are invalid
  10. */
  11. function pagination<T = any>(list: T[], pageNo: number, pageSize: number): T[] {
  12. if (pageNo < 1) throw new Error('Page number must be positive');
  13. if (pageSize < 1) throw new Error('Page size must be positive');
  14. const offset = (pageNo - 1) * Number(pageSize);
  15. const ret =
  16. offset + pageSize >= list.length
  17. ? list.slice(offset)
  18. : list.slice(offset, offset + pageSize);
  19. return ret;
  20. }
  21. export function usePagination<T = any>(list: Ref<T[]>, pageSize: number) {
  22. const currentPage = ref(1);
  23. const pageSizeRef = ref(pageSize);
  24. const totalPages = computed(() =>
  25. Math.ceil(unref(list).length / unref(pageSizeRef)),
  26. );
  27. const paginationList = computed(() => {
  28. return pagination(unref(list), unref(currentPage), unref(pageSizeRef));
  29. });
  30. const total = computed(() => {
  31. return unref(list).length;
  32. });
  33. function setCurrentPage(page: number) {
  34. if (page < 1 || page > unref(totalPages)) {
  35. throw new Error('Invalid page number');
  36. }
  37. currentPage.value = page;
  38. }
  39. function setPageSize(pageSize: number) {
  40. if (pageSize < 1) {
  41. throw new Error('Page size must be positive');
  42. }
  43. pageSizeRef.value = pageSize;
  44. // Reset to first page to prevent invalid state
  45. currentPage.value = 1;
  46. }
  47. return { setCurrentPage, total, setPageSize, paginationList };
  48. }