资讯动态

Vue3分页(Pagination)

发布时间:2026/8/29 13:48:20 来源:尧图企业网站定制
Vue2分页Pagination可自定义设置以下属性当前页数v-model:page类型number默认 1每页条数v-model:pageSize类型number默认 10数据总数total类型number默认 0是否禁用disabled类型boolean默认 false显示的页码数pageAmount类型number默认 5只有一页时是否隐藏分页hideOnSinglePage类型boolean默认 false是否可以快速跳转至某页showQuickJumper类型boolean默认 false快速跳转组件 propsjumperProps参考 Input Props类型object默认 {}是否展示 pageSize 切换器showSizeChanger类型boolean默认 undefined当 total 大于 50 时默认为 truepageSize 切换器组件 propschangerProps参考 Select Props类型object默认 {}设置每页可以显示多少条pageSizeOptions类型string[] | number[]默认 [10, 20, 50, 100]用于显示数据总量和当前数据顺序showTotal类型boolean | | ((total: number, range: number[]) string)默认 false分页展示位置placement类型left | center | right默认 center分页按钮大小size类型large | middle | small默认 large效果如下图在线预览①创建自定义分页组件Pagination.vue其中引入使用了以下组件与工具函数Vue3选择器SelectVue3输入框Input获取依赖注入 useInjectscript setup langts import { ref, computed, watch, nextTick } from vue import Input from components/input import Select from components/select import { useInject } from components/utils export interface Props { page?: number // (v-model) 当前页数 pageSize?: number // (v-model) 每页条数 total?: number // 数据总数 disabled?: boolean // 是否禁用 pageAmount?: number // 显示的页码数 hideOnSinglePage?: boolean // 只有一页时是否隐藏分页 showQuickJumper?: boolean // 是否可以快速跳转至某页 jumperProps?: object // 快速跳转组件 props参考 Input 组件 Props showSizeChanger?: boolean // 是否展示 pageSize 切换器当 total 大于 50 时默认为 true changerProps?: object // pageSize 切换器组件 props参考 Select 组件 Props pageSizeOptions?: string[] | number[] // 设置每页可以显示多少条 showTotal?: boolean | ((total: number, range: number[]) string) // 用于显示数据总量和当前数据顺序 placement?: left | center | right // 分页展示位置靠左 left居中 center靠右 right size?: large | middle | small // 分页按钮大小 } const props withDefaults(definePropsProps(), { page: 1, pageSize: 10, total: 0, disabled: false, pageAmount: 5, hideOnSinglePage: false, showQuickJumper: false, jumperProps: () ({}), showSizeChanger: undefined, changerProps: () ({}), pageSizeOptions: () [10, 20, 50, 100], showTotal: false, placement: center, size: large }) const currentPage refnumber(props.page) // 当前页数 const currentPageSize refnumber(props.pageSize) // 每页条数 const pageListRef refHTMLElement[] | null(null) // pageList 生成的 page 元素引用 const jumpNumber ref() // 跳转的页码 const forwardMore ref(false) // 左省略号展示 const backwardMore ref(false) // 右省略号展示 const { colorPalettes } useInject(Pagination) // 主题色注入 const emits defineEmits([update:page, update:pageSize, change, pageSizeChange]) const totalPage computed(() { // 总页数 return Math.ceil(props.total / currentPageSize.value) // 向上取整 }) const totalText computed(() { if (typeof props.showTotal boolean) { if (props.showTotal) { return 共 ${props.total} 条 } } else { const first (currentPage.value - 1) * currentPageSize.value 1 const last currentPage.value * currentPageSize.value props.total ? props.total : currentPage.value * currentPageSize.value return props.showTotal(props.total, [first, last]) } return null }) const pageList computed(() { // 获取显示的页码数组 return dealPageList(currentPage.value).filter((n) n ! 1 n ! totalPage.value) }) const showPageSizeChanger computed(() { if (typeof props.showSizeChanger boolean) { return props.showSizeChanger } else { // undefined return props.total 50 } }) const selectOptions computed(() { const pageSizeOptipns [currentPageSize.value, ...props.pageSizeOptions].map((pageSize: number | string) Number(pageSize) ) return Array.from(new Set(pageSizeOptipns)) .sort((a: number, b: number) a - b) .map((pageSize: number) { return { label: ${pageSize} 条/页, value: pageSize } }) }) const selectHeight computed(() { const heightMap { small: 24, middle: 28, large: 32 } return heightMap[props.size] || heightMap[large] }) const optionsSize computed(() { if (props.size small) { return small } return middle }) watch( () props.page, (to) { currentPage.value to } ) watch( () props.pageSize, (to: number) { currentPageSize.value to } ) function dealPageList(curPage: number): number[] { var resList [] var offset Math.floor(props.pageAmount / 2) var pager { start: curPage - offset, end: curPage offset } if (pager.start 1) { pager.end pager.end (1 - pager.start) pager.start 1 } if (pager.end totalPage.value) { pager.start pager.start - (pager.end - totalPage.value) pager.end totalPage.value } if (pager.start 1) { pager.start 1 } if (pager.start 1) { forwardMore.value true } else { forwardMore.value false } if (pager.end totalPage.value) { backwardMore.value true } else { backwardMore.value false } // 生成要显示的页码数组 for (let i pager.start; i pager.end; i) { resList.push(i) } return resList } function onPageForward(): void { currentPage.value currentPage.value - props.pageAmount 0 ? currentPage.value - props.pageAmount : 1 emits(update:page, currentPage.value) emits(change, currentPage.value, currentPageSize.value) } function onPageBackward(): void { currentPage.value currentPage.value props.pageAmount totalPage.value ? currentPage.value props.pageAmount : totalPage.value emits(update:page, currentPage.value) emits(change, currentPage.value, currentPageSize.value) } async function onPageJump(): Promisevoid { let num Number(jumpNumber.value) // 转换为数字 if (jumpNumber.value Number.isInteger(num)) { // 是否为整数 if (num 1) { num 1 } if (num totalPage.value) { num totalPage.value } onPageChange(num) } await nextTick() jumpNumber.value undefined // 清空跳转输入框 } // 聚焦当前页码 async function activePageFocus(activePage: number) { await nextTick() const targetIndex pageList.value.findIndex((page: number) page activePage) pageListRef.value?.[targetIndex].focus() } function onPageChange(page: number, inPageList: boolean false): boolean | void { if (page 0 || page totalPage.value 1) { return false } // 点击的页码不是当前页码 if (currentPage.value ! page) { currentPage.value page if (inPageList) { activePageFocus(page) } emits(update:page, currentPage.value) emits(change, currentPage.value, currentPageSize.value) } } function onPageNext(e: Event, page: number): void { ;(e.target as HTMLElement).focus() onPageChange(page) } // pageSize 切换器变化时的回调 function onPageSizeChange(pageSize: number): void { currentPageSize.value pageSize const maxPage Math.ceil(props.total / pageSize) if (currentPage.value maxPage) { currentPage.value maxPage } emits(update:page, currentPage.value) emits(update:pageSize, currentPageSize.value) emits(pageSizeChange, currentPage.value, currentPageSize.value) emits(change, currentPage.value, currentPageSize.value) } /script template div classpagination-wrap :class[ pagination-${placement}, { pagination-small: size small, pagination-middle: size middle, pagination-disabled: disabled, pagination-hidden: !total || (hideOnSinglePage total currentPageSize) } ] :style--pagination-primary-color: ${colorPalettes[5]}; --pagination-primary-color-focus-visible: ${colorPalettes[2]}; span classpagination-total-text v-iftotalText{{ totalText }}/span span tabindex0 classpagination-prev :class{ pagination-item-disabled: currentPage 1 } keydown.enter.preventdisabled ? () false : onPageChange(currentPage - 1) clickdisabled || currentPage 1 ? () false : onPageChange(currentPage - 1) svg classarrow-svg viewBox64 64 896 896 >script setup langts import Pagination from ./Pagination.vue import { ref } from vue import type { PaginationProps } from vue-amazing-ui const page ref(1) const pageSize ref(10) const total ref(500) const placementOptions [ { label: left, value: left }, { label: center, value: center }, { label: right, value: right } ] const placement refPaginationProps[placement](left) const sizeOptions [ { label: small, value: small }, { label: middle, value: middle }, { label: large, value: large } ] const size refPaginationProps[size](middle) function onChange(page: number, pageSize: number) { // 页码 page 或每页条数 pageSize 改变的回调 console.log(change page, page) console.log(change pageSize, pageSize) } function pageSizeChange(page: number, pageSize: number) { // 每页条数 pageSize 变化的回调 console.log(pageSizeChange page, page) console.log(pageSizeChange pageSize, pageSize) } /script template div h1{{ $route.name }} {{ $route.meta.title }}/h1 h2 classmt30 mb10基本使用/h2 Pagination v-model:pagepage :total50 changeonChange / h2 classmt30 mb10自定义位置/h2 Flex vertical Radio :optionsplacementOptions v-model:valueplacement button button-stylesolid / Pagination v-model:pagepage :totaltotal :placementplacement changeonChange / /Flex h2 classmt30 mb10三种尺寸/h2 Flex vertical Radio :optionssizeOptions v-model:valuesize button button-stylesolid / Pagination v-model:pagepage :sizesize :totaltotal show-quick-jumper changeonChange / /Flex h2 classmt30 mb10自定义 pageSize 切换选项/h2 Pagination v-model:pagepage v-model:page-sizepageSize :totaltotal :page-size-options[10, 20, 30, 40, 50] changeonChange pageSizeChangepageSizeChange / h2 classmt30 mb10隐藏 pageSize 切换器/h2 Pagination v-model:pagepage :totaltotal :show-size-changerfalse changeonChange / h2 classmt30 mb10快速跳转/h2 Pagination v-model:pagepage :totaltotal show-quick-jumper changeonChange / h2 classmt30 mb10数据总数/h2 Flex vertical Pagination v-model:pagepage :totaltotal show-total changeonChange / Pagination v-model:pagepage :totaltotal :show-total(total: number) Total ${total} items changeonChange / Pagination v-model:pagepage :totaltotal :show-total(total: number, range: number[]) ${range[0]}-${range[1]} of ${total} items changeonChange / /Flex h2 classmt30 mb10禁用/h2 Pagination disabled v-model:pagepage :totaltotal show-quick-jumper changeonChange / /div /template

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价