|
| 1 | +--- |
| 2 | +title: "PrimevueV4踩坑日记(一)" # 文章标题 |
| 3 | +date: 2025-10-17T11:40:00+08:00 # 文章创建日期 |
| 4 | +draft: false # 是否为草稿,true 表示草稿,不会在网站上显示 |
| 5 | +author: "runshell" # 文章作者 |
| 6 | +description: "今日踩坑:Primevue Datatable组件分页问题" # 文章描述 |
| 7 | +tags: ["Primevue", "vue3", "前端"] # 文章标签 |
| 8 | +categories: ["WEB开发"] # 文章分类 |
| 9 | +--- |
| 10 | + |
| 11 | +# 坑 |
| 12 | + |
| 13 | +Primevue Datatable 组件分页时,无论 totalRecords 设置为多少,分页总页数都为 1。 |
| 14 | + |
| 15 | +# 解决方法 |
| 16 | + |
| 17 | +如果服务端单次只返回了一页数据,将 totalRecords 设置为该数据的总条数,同时将 lazy 设置为 true。 |
| 18 | + |
| 19 | +# 分析过程 |
| 20 | + |
| 21 | +Datatable 组件的分页逻辑是根据 totalRecords 和 rows 计算出总页数。如果 lazy 设置为 true,那么总行数为 totalRecords,否则总行数为 data.length,不读取 totalRecords 值。 |
| 22 | +参考:[Datatable 组件的源码](https://github.com/primefaces/primevue/blob/master/packages/primevue/src/datatable/DataTable.vue#L2090) |
| 23 | + |
| 24 | +部分代码片段如下: |
| 25 | + |
| 26 | +```vue |
| 27 | +<template> |
| 28 | + <DTPaginator |
| 29 | + v-if="paginatorTop" |
| 30 | + :rows="d_rows" |
| 31 | + :first="d_first" |
| 32 | + :totalRecords="totalRecordsLength" |
| 33 | + :pageLinkSize="pageLinkSize" |
| 34 | + :template="paginatorTemplate" |
| 35 | + :rowsPerPageOptions="rowsPerPageOptions" |
| 36 | + :currentPageReportTemplate="currentPageReportTemplate" |
| 37 | + :class="cx('pcPaginator', { position: 'top' })" |
| 38 | + @page="onPage($event)" |
| 39 | + :alwaysShow="alwaysShowPaginator" |
| 40 | + :unstyled="unstyled" |
| 41 | + :data-p-top="true" |
| 42 | + :pt="ptm('pcPaginator')" |
| 43 | + > |
| 44 | +</template> |
| 45 | +
|
| 46 | +<script> |
| 47 | +totalRecordsLength() { |
| 48 | + if (this.lazy) { |
| 49 | + return this.totalRecords; |
| 50 | + } else { |
| 51 | + const data = this.processedData; |
| 52 | +
|
| 53 | + return data ? data.length : 0; |
| 54 | + } |
| 55 | +} |
| 56 | +</script> |
| 57 | +``` |
| 58 | + |
| 59 | +# 代码示例 |
| 60 | + |
| 61 | +```vue |
| 62 | +<script setup> |
| 63 | +import { ref, onMounted } from "vue"; |
| 64 | +
|
| 65 | +const items = ref([]); |
| 66 | +const totalRecords = ref(0); |
| 67 | +const loading = ref(false); |
| 68 | +const rows = ref(10); |
| 69 | +
|
| 70 | +// 加载数据 |
| 71 | +async function loadData(page = 0) { |
| 72 | + loading.value = true; |
| 73 | +
|
| 74 | + try { |
| 75 | + const response = await fetch( |
| 76 | + `/api/data/?page=${page + 1}&page_size=${rows.value}` |
| 77 | + ); |
| 78 | + const result = await response.json(); |
| 79 | +
|
| 80 | + items.value = result.results; |
| 81 | + totalRecords.value = result.count; // 服务器返回的总记录数 |
| 82 | + } catch (error) { |
| 83 | + console.error("加载失败:", error); |
| 84 | + } finally { |
| 85 | + loading.value = false; |
| 86 | + } |
| 87 | +} |
| 88 | +
|
| 89 | +function onPage(event) { |
| 90 | + loadData(event.page); |
| 91 | +} |
| 92 | +
|
| 93 | +onMounted(() => { |
| 94 | + loadData(0); |
| 95 | +}); |
| 96 | +</script> |
| 97 | +
|
| 98 | +<template> |
| 99 | + <DataTable :value="items" :lazy="true" <!-- 关键:必须启用 lazy --> |
| 100 | + :paginator="true" :rows="rows" :totalRecords="totalRecords" |
| 101 | + :loading="loading" @page="onPage" tableStyle="min-width: 50rem" > |
| 102 | + <Column field="id" header="ID"></Column> |
| 103 | + <Column field="name" header="名称"></Column> |
| 104 | + <Column field="category" header="分类"></Column> |
| 105 | + </DataTable> |
| 106 | +</template> |
| 107 | +``` |
0 commit comments