useClientPagination.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { computed, ref, watch, type Ref } from 'vue'
  2. /** 默认每页条数 */
  3. export const DEFAULT_PAGE_SIZE = 10
  4. /** 可选每页条数 */
  5. export const PAGE_SIZES = [10, 20, 50]
  6. /**
  7. * 前端列表分页(对接真实接口前先对本地数组切片)
  8. * @param source 完整列表 ref,或返回列表的 getter(适合 computed)
  9. */
  10. function asArray<T>(value: unknown): T[] {
  11. if (Array.isArray(value)) return value
  12. if (value && typeof value === 'object') {
  13. const list = (value as { list?: unknown }).list
  14. if (Array.isArray(list)) return list as T[]
  15. }
  16. return []
  17. }
  18. export function useClientPagination<T>(
  19. source: Ref<T[]> | (() => T[]),
  20. options?: { pageSize?: number },
  21. ) {
  22. const page = ref(1)
  23. const pageSize = ref(options?.pageSize ?? DEFAULT_PAGE_SIZE)
  24. const sourceList = computed(() =>
  25. asArray<T>(typeof source === 'function' ? source() : source.value),
  26. )
  27. const total = computed(() => sourceList.value.length)
  28. const pageCount = computed(() =>
  29. Math.max(1, Math.ceil(total.value / pageSize.value) || 1),
  30. )
  31. const pagedList = computed(() => {
  32. const start = (page.value - 1) * pageSize.value
  33. return sourceList.value.slice(start, start + pageSize.value)
  34. })
  35. function resetPage() {
  36. page.value = 1
  37. }
  38. function goFirst() {
  39. page.value = 1
  40. }
  41. function goLast() {
  42. page.value = pageCount.value
  43. }
  44. // 数据量或每页条数变化时,纠正越界页码
  45. watch([total, pageSize], () => {
  46. if (page.value > pageCount.value) {
  47. page.value = pageCount.value
  48. }
  49. })
  50. return {
  51. page,
  52. pageSize,
  53. total,
  54. pageCount,
  55. pagedList,
  56. resetPage,
  57. goFirst,
  58. goLast,
  59. }
  60. }