Element UI 無論是 Vue2 或是 Vue3 的版本,其分頁條 ( Pagination ) 和 Table 表格本身是分開處理的。因此在每頁項目數 ( limit )、當前顯示頁數 ( currentPage ) 搭配搜尋條件和排序條件時,會遇上 limit 和 currentPage 有時間差的狀況。這邊筆記下處理方法。
思路
1. 藉由對 <el-pagination> 的再次封裝而成,建議需傳入 total, limit 和 page 三個參數。
2. 當 limit 的值改變時,會觸發 limit 和 page 的值進行變動 ( 因為 page 的值有機會因為 limit 改變而超過 )。當父層接收到兩次 emit 出的值時,要藉由 total 來進行判斷
3. 承接第二點,因為在排序和搜尋的字串條件不變的情況下,僅改變 limit 大小並不會造成 total 變動。所以可以在打 api 取資料前利用條件進行判斷,排除掉不合理的請求。
程式碼
1. 若 total 不是 0 且 目標頁數 > Math.ceil(total / limit),這會是一個不必要送出的請求
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import request, { AxiosResponse } from '@/utils/httpRequest' | |
export function getSpaces(query:Record<string, any>, total = 0):Promise<AxiosResponse> | undefined { | |
if ((query.page > Math.ceil(total / Number(query.limit))) && total !== 0) return | |
return request({ | |
url: `list`, | |
method: 'get', | |
params: query | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- From youlaitech/vue3-element-admin --> | |
<template> | |
<div :class="{ hidden: hidden }" class="pagination-container"> | |
<el-pagination | |
:background="background" | |
v-model:current-page="currentPage" | |
v-model:page-size="pageSize" | |
:layout="layout" | |
:page-sizes="pageSizes" | |
:total="total" | |
@size-change="handleSizeChange" | |
@current-change="handleCurrentChange" | |
/> | |
</div> | |
</template> | |
<script setup lang="ts"> | |
import { computed, PropType } from 'vue' | |
import { scrollTo } from '@/utils/scroll-to' | |
const props = defineProps({ | |
total: { | |
required: true, | |
type: Number as PropType<number>, | |
default: 0 | |
}, | |
page: { | |
type: Number, | |
default: 1 | |
}, | |
limit: { | |
type: Number, | |
default: 20 | |
}, | |
pageSizes: { | |
type: Array as PropType<number[]>, | |
default() { | |
return [10, 20, 30, 50] | |
} | |
}, | |
layout: { | |
type: String, | |
default: 'total, sizes, prev, pager, next, jumper' | |
}, | |
background: { | |
type: Boolean, | |
default: true | |
}, | |
autoScroll: { | |
type: Boolean, | |
default: true | |
}, | |
hidden: { | |
type: Boolean, | |
default: false | |
} | |
}) | |
const emit = defineEmits(['update:page', 'update:limit', 'pagination']) | |
const currentPage = computed<number | undefined>({ | |
get: () => props.page, | |
set: value => { | |
emit('update:page', value) | |
} | |
}) | |
const pageSize = computed<number | undefined>({ | |
get() { | |
return props.limit | |
}, | |
set(val) { | |
emit('update:limit', val) | |
} | |
}) | |
function handleSizeChange(val: number) { | |
emit('pagination', { page: currentPage, limit: val }) | |
if (props.autoScroll) { | |
scrollTo(0, 800) | |
} | |
} | |
function handleCurrentChange(val: number) { | |
currentPage.value = val | |
emit('pagination', { page: val, limit: props.limit }) | |
if (props.autoScroll) { | |
scrollTo(0, 800) | |
} | |
} | |
</script> |