use-pagination.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import type { Ref } from 'vue';
  2. import { computed, ref, unref, watch } 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>(
  22. list: Ref<T[]>,
  23. pageSize: number,
  24. totalChangeToFirstPage = true,
  25. ) {
  26. const currentPage = ref(1);
  27. const pageSizeRef = ref(pageSize);
  28. const totalPages = computed(() =>
  29. Math.ceil(unref(list).length / unref(pageSizeRef)),
  30. );
  31. const paginationList = computed(() => {
  32. return pagination(unref(list), unref(currentPage), unref(pageSizeRef));
  33. });
  34. const total = computed(() => {
  35. return unref(list).length;
  36. });
  37. if (totalChangeToFirstPage) {
  38. watch(total, () => {
  39. setCurrentPage(1);
  40. });
  41. }
  42. function setCurrentPage(page: number) {
  43. if (page === 1 && unref(totalPages) === 0) {
  44. currentPage.value = 1;
  45. } else {
  46. if (page < 1 || page > unref(totalPages)) {
  47. throw new Error('Invalid page number');
  48. }
  49. currentPage.value = page;
  50. }
  51. }
  52. function setPageSize(pageSize: number) {
  53. if (pageSize < 1) {
  54. throw new Error('Page size must be positive');
  55. }
  56. pageSizeRef.value = pageSize;
  57. // Reset to first page to prevent invalid state
  58. currentPage.value = 1;
  59. }
  60. return { setCurrentPage, total, setPageSize, paginationList, currentPage };
  61. }