SimplePagerDataLoader.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { watch, ref, computed, type Ref } from "vue"
  2. import type { ILoaderCommon, LoaderLoadType } from "./LoaderCommon";
  3. export interface ISimplePageListLoader<T, P> extends ILoaderCommon<P> {
  4. list: Ref<T[]>;
  5. page: Ref<number>;
  6. next: () => Promise<void>;
  7. prev: () => Promise<void>;
  8. total: Ref<number>;
  9. totalPages: Ref<number>;
  10. }
  11. /**
  12. * 简单分页数据封装。
  13. *
  14. * 该封装了分页数据的加载、分页、上一页、下一页等功能。当页码发生变化时,会自动调用加载函数。
  15. * 简单分页同时只能显示一页数据,重新加载会覆盖之前的数据。
  16. *
  17. * 使用示例:
  18. * ```ts
  19. * const { data, page, total, loading } = useSimplePagerDataLoader(10, async (page, pageSize) => {
  20. * const res = await fetch(`/api/data?page=${page}&pageSize=${pageSize}`);
  21. * const data = await res.json();
  22. * return {
  23. * data,
  24. * page: res.page,
  25. * total: res.total,
  26. * };
  27. * });
  28. * ```
  29. *
  30. * @param pageSize 一页的数量
  31. * @param loader 加载函数
  32. * @returns
  33. */
  34. export function useSimplePagerDataLoader<T, P = any>(
  35. pageSize: number,
  36. loader: (page: number, pageSize: number, params?: P) => Promise<{
  37. data: T[],
  38. total: number,
  39. }>) : ISimplePageListLoader<T, P>
  40. {
  41. const page = ref(0);
  42. const list = ref<T[]>([]) as Ref<T[]>;
  43. const total = ref(0);
  44. const totalPages = computed(() => Math.ceil(total.value / pageSize));
  45. const loadStatus = ref<LoaderLoadType>('loading');
  46. const loadError = ref('');
  47. watch(page, async () => {
  48. await loadData(lastParams, false);
  49. });
  50. let lastParams: P | undefined;
  51. let loading = false;
  52. async function loadData(params?: P, refresh: boolean = false) {
  53. if (loading)
  54. return;
  55. if (params)
  56. lastParams = params;
  57. if (refresh) {
  58. page.value = 1;
  59. }
  60. list.value = [];
  61. loadStatus.value = 'loading';
  62. loading = true;
  63. try {
  64. const res = (await loader(page.value, pageSize, lastParams));
  65. list.value = list.value.concat(res.data);
  66. total.value = res.total;
  67. loadStatus.value = res.data.length > 0 ? 'finished' : 'nomore';
  68. loadError.value = '';
  69. loading = false;
  70. } catch(e) {
  71. loadError.value = '' + e;
  72. loadStatus.value = 'error';
  73. loading = false;
  74. }
  75. }
  76. /**
  77. * 下一页
  78. */
  79. async function next() {
  80. if (page.value > total.value)
  81. return;
  82. page.value++;
  83. await loadData(lastParams, false);
  84. }
  85. /**
  86. * 上一页
  87. */
  88. async function prev() {
  89. if (page.value <= 1)
  90. return;
  91. page.value--;
  92. await loadData(lastParams, false);
  93. }
  94. return {
  95. loadData,
  96. next,
  97. prev,
  98. /**
  99. * 数据
  100. */
  101. list,
  102. /**
  103. * 当前页码
  104. */
  105. page,
  106. /**
  107. * 总数据条数
  108. */
  109. total,
  110. /**
  111. * 总页数
  112. */
  113. totalPages,
  114. loadError,
  115. loadStatus,
  116. }
  117. }