useServerPagination.ts 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { ref, watch, type Ref } from 'vue'
  2. export type ServerPageFetcher<T> = (pageNum: number, pageSize: number) => Promise<{
  3. list: T[]
  4. total: number
  5. }>
  6. /**
  7. * 服务端分页:翻页/改 pageSize 时重新请求(不自动 immediate,由页面 resetAndLoad 触发)。
  8. */
  9. export function useServerPagination<T>(
  10. fetcher: ServerPageFetcher<T>,
  11. options?: { pageSize?: number },
  12. ) {
  13. const page = ref(1)
  14. const pageSize = ref(options?.pageSize ?? 10)
  15. const total = ref(0)
  16. const list = ref<T[]>([]) as Ref<T[]>
  17. const loading = ref(false)
  18. let skipWatch = false
  19. async function load() {
  20. loading.value = true
  21. try {
  22. const res = await fetcher(page.value, pageSize.value)
  23. list.value = res.list || []
  24. total.value = Number(res.total || 0)
  25. } finally {
  26. loading.value = false
  27. }
  28. }
  29. async function resetAndLoad() {
  30. skipWatch = true
  31. page.value = 1
  32. skipWatch = false
  33. await load()
  34. }
  35. watch(page, () => {
  36. if (skipWatch) return
  37. void load()
  38. })
  39. watch(pageSize, () => {
  40. skipWatch = true
  41. page.value = 1
  42. skipWatch = false
  43. void load()
  44. })
  45. return {
  46. page,
  47. pageSize,
  48. total,
  49. list,
  50. loading,
  51. load,
  52. resetAndLoad,
  53. }
  54. }