Angular 实现分页器组件
很感谢 angular实现简单的pagination分页组件 - Amor丶Diamond - 博客园 (cnblogs.com) , 我根据这位博主代码做了修改, 增加了跳转和每页行数功能.
先看图:
// 可配置项
// totalItem 数据总条数
// maxSize:最多显示几页
// pageSizes: 行/页
// moreBtn:是否显示省略号提示更多分页
// turnBtn:是否显示上下翻页
// fastTurnBtn:是否显示首页和末页
// goToBtn: 是否显示跳转
// pageInfoIsShow: 是否显示总页数
// pageSizeIsShow: 是否显示 行/页, 如果关闭: 行/页 = 10
paginator.component.html:
<div> <ul class="custom-pagination"> <li class="page-size" *ngIf="pageSizeIsShow"> 行/页:<select [(ngModel)]="pageSize" (change)="selectItem()"> <option *ngFor="let item of pageSizes" [value]="item">{{ item }}</option> </select> </li> <li class="page-item first-page" *ngIf="fastTurnBtn" [ngClass]="{'disabled': currentPage <= 1}" (click)="goToPage(1)"><span><<</span></li> <li class="page-item prev-page" *ngIf="turnBtn" [ngClass]="{'disabled': currentPage <= 1}" (click)="preNextPage('上一页')"><span><</span></li> <li class="page-item left-more-page" *ngIf="showLeftMoreStatus && moreBtn" (click)="leftMoreClick()" title="查看更多"> <span></span></li> <li class="page-item" *ngFor="let item of showPageList;" [ngClass]="{'active': item === currentPage}" (click)="goToPage(item)">{{item}}</li> <li class="page-item right-more-page" *ngIf="showRightMoreStatus && moreBtn" (click)="rightMoreClick()" title="查看更多"><span></span></li> <li class="page-item next-page" *ngIf="turnBtn" [ngClass]="{'disabled': currentPage >= totalPage}" (click)="preNextPage('下一页')"><span>></span></li> <li class="page-item last-page" *ngIf="fastTurnBtn" [ngClass]="{'disabled': currentPage >= totalPage}" (click)="goToPage(totalPage)"><span>>></span></li> <li class="page-goto" *ngIf="goToBtn"> <input type="number" [(ngModel)]="goToPageNum" min="1"> <button (click)="goToPage(goToPageNum)">跳转</button> </li> <li class="page-pageInfo" *ngIf="pageInfoIsShow"><span> 共 {{totalPage}} 页</span></li> </ul> </div>
paginator.component.ts
import {Component, OnInit, OnChanges, Input, Output, EventEmitter} from '@angular/core';
import {noop} from "rxjs";
@Component({
selector: 'my-paginator',
templateUrl: './paginator.component.html',
styleUrls: ['./paginator.component.scss']
})
export class PaginatorComponent implements OnInit, OnChanges {
// 可配置项
// totalItem 数据总条数
// maxSize:最多显示几页
// pageSizes: 行/页
// moreBtn:是否显示省略号提示更多分页
// turnBtn:是否显示上下翻页
// fastTurnBtn:是否显示首页和末页
// goToBtn: 是否显示跳转
// pageInfoIsShow: 是否显示总页数
// pageSizeIsShow: 是否显示 行/页, 如果关闭, 行/页 = 10
private static defaultTotalItem = 0;
private static defaultMaxSize = 10;
private static defaultPageSizes = [10, 15, 20, 25, 30];
private static defaultMoreBtn = true;
private static defaultTurnBtn = true;
private static defaultFastTurnBtn = true;
private static defaultGoToBtn = true;
private static defaultPageInfoIsShow = true;
private static defaultPageSizeIsShow = true;
private static defaultTotalPage = 0;
@Input() totalItem: number = PaginatorComponent.defaultTotalItem;
@Input() maxSize: number = PaginatorComponent.defaultMaxSize;
@Input() pageSizes = PaginatorComponent.defaultPageSizes;
@Input() moreBtn: Boolean = PaginatorComponent.defaultMoreBtn;
@Input() turnBtn: Boolean = PaginatorComponent.defaultTurnBtn;
@Input() fastTurnBtn: Boolean = PaginatorComponent.defaultFastTurnBtn;
@Input() goToBtn: Boolean = PaginatorComponent.defaultGoToBtn;
@Input() pageInfoIsShow: Boolean = PaginatorComponent.defaultPageInfoIsShow;
@Input() pageSizeIsShow: Boolean = PaginatorComponent.defaultPageSizeIsShow;
@Output() currentPageChange: EventEmitter<Number> = new EventEmitter;
@Output() pageSizeChange: EventEmitter<Number> = new EventEmitter;
private pageSize = PaginatorComponent.defaultPageSizes[0];
private currentPage = 1;
totalPage = 0;
goToPageNum = 1;
showPageList: Array<number> = [];
showEndPage = 0;
showBeginPage = 0;
showLeftMoreStatus = false;
showRightMoreStatus = false;
constructor() {
}
ngOnInit: () => void = noop;
ngOnChanges() {
this.initPages();
}
currentChange() {
this.currentPageChange.emit(this.currentPage);
}
preNextPage(page: string) {
if (this.totalPage <= 1) {
return;
}
let pageNum;
if (page === '上一页') {
if (this.currentPage <= 1) return;
pageNum = this.currentPage === 1 ? this.currentPage : this.currentPage - 1;
} else {
if (this.currentPage >= this.totalPage) return;
pageNum = this.currentPage === this.totalPage ? this.currentPage : this.currentPage + 1;
}
if (pageNum !== this.currentPage) {
this.currentPage = pageNum;
this.changePageHandle();
}
}
goToPage(page: number) {
if (page && this.currentPage !== page) {
if (0 <= page && page <= this.totalPage) {
this.currentPage = page;
} else if (page > this.totalPage) {
this.currentPage = this.totalPage;
} else {
this.currentPage = 1;
}
this.changePageHandle();
}
}
leftMoreClick() {
// 左更多按钮点击后处理当前显示的分页
const startPage = this.showBeginPage - this.maxSize;
const endPage = startPage + this.maxSize;
this.currentPage -= Math.ceil((endPage - startPage) / 2);
this.changePageHandle();
}
rightMoreClick() {
// 右更多分页按钮点击后处理当前显示的分页
let startPage;
if ((this.showEndPage + this.maxSize) < this.totalPage) {
startPage = this.showEndPage + this.maxSize;
} else {
startPage = this.totalPage - this.maxSize;
}
const endPage = startPage + this.maxSize;
this.currentPage += Math.ceil((endPage - startPage) / 2);
this.changePageHandle();
}
formatPages() {
const maxSizeHalf = this.maxSize / 2;
const maxSizeHalfFloor = Math.floor(maxSizeHalf);
const minBoundary = this.showEndPage - Math.ceil(maxSizeHalf); // 需要向后处理显示分页数据的分界点
const maxBoundary = this.showBeginPage + maxSizeHalfFloor; // 需要向前处理显示分页数据的分界点
if (this.currentPage > minBoundary || this.currentPage < maxBoundary) {
this.showBeginPage = this.currentPage - maxSizeHalfFloor > 1 ? this.currentPage - maxSizeHalfFloor : 1;
this.showEndPage = (this.showBeginPage + this.maxSize - 1) < this.totalPage ? (this.showBeginPage + this.maxSize - 1) : this.totalPage;
if (this.showEndPage - this.showBeginPage < this.maxSize - 1) {
this.showBeginPage = this.showEndPage - this.maxSize > 1 ? this.showEndPage - (this.maxSize - 1) : 1;
}
this.handlePagesData(this.showBeginPage, this.showEndPage);
}
// console.log(this.showPageList);
}
// 根据传入的参数初始化页码
initPages() {
// 初始化 pageSizes
if (this.pageSizeIsShow) {
for (let i = 0; i < this.pageSizes.length; i++) {
if (this.pageSizes[i] <= 0) {
this.pageSizes.splice(i, 1);
i--;
}
}
if (this.pageSizes.length === 0) {
this.pageSizes = PaginatorComponent.defaultPageSizes;
}
// 初始化 pageSize
this.pageSize = this.pageSizes[0];
}
if (this.totalItem >= 0 && this.maxSize >= 1) {
let startPage = 1;
this.showBeginPage = startPage;
this.showEndPage = startPage + this.maxSize - 1;
this.totalPage = Math.ceil(this.totalItem / this.pageSize);
if (this.totalPage < this.maxSize) {
this.showEndPage = this.totalPage;
}
} else {
// 如果初始值不正确, 就是用默认值, TODO 不显示
this.totalPage = PaginatorComponent.defaultTotalPage;
this.maxSize = PaginatorComponent.defaultMaxSize;
this.showBeginPage = 1;
this.showEndPage = 1;
}
this.handlePagesData(this.showBeginPage, this.showEndPage);
this.showPagesMore();
}
handlePagesData(begin, end) {
// 循环生成要显示的页码数据
this.showPageList = [];
for (let i = begin; i <= end; i++) {
this.showPageList.push(i);
}
}
showPagesMore() {
if (this.currentPage > this.maxSize * 2) {
this.showLeftMoreStatus = true;
} else {
this.showLeftMoreStatus = false;
}
if (this.showEndPage < this.totalPage) {
this.showRightMoreStatus = true;
} else {
this.showRightMoreStatus = false;
}
}
changePageHandle() {
// 翻页后触发方法
this.formatPages();
this.showPagesMore();
this.onModelChange(this.currentPage); // 触发ngModel绑定的数据更新
this.currentPageChange.emit(this.currentPage);
this.pageSizeChange.emit(this.pageSize);
}
onModelChange: Function = () => {
};
// 在选择一页显示多少行后就将值传回
selectItem() {
this.totalPage = Math.ceil(this.totalItem / this.pageSize);
this.currentPage = 1;
this.changePageHandle();
}
// 页面的值改变,调用改方法,并调用onModelChange传入改变后的值,实现值的回传
writeValue(val): void {
// 页面初始化时时,调用该方法,传入初始值
if (val) {
this.currentPage = val;
}
}
registerOnChange(fn: any): void {
// 页面值改变时,调用该方法,传入新值实现回传
this.onModelChange = fn;
}
registerOnTouched(fn: any): void {
}
protected readonly print = print;
protected readonly console = console;
}
paginator.component.scss
// custom-pagination.css .custom-pagination { overflow: hidden; margin: 10px 0; text-align: center; } .page-size { display: inline-block; height: 25px; line-height: 23px; border-radius: 3px; margin: 0 15px; cursor: pointer; user-select: none; vertical-align: middle; } input { width: 30px; } .page-item { display: inline-block; width: 25px; height: 25px; line-height: 23px; border: 1px solid #06a0e7; color: #06a0e7; text-align: center; border-radius: 3px; margin: 0 2px; cursor: pointer; user-select: none; vertical-align: middle; } .page-goto { display: inline-block; height: 25px; line-height: 23px; text-align: center; border-radius: 3px; margin: 0 15px; cursor: pointer; user-select: none; vertical-align: middle; } .page-pageInfo{ display: inline-block; } .prev-page, .next-page { width: auto; padding: 0 2px; } .page-item.active, .page-goto.active { border-color: #06a0e7; background: #06a0e7; color: #fff; } .disabled { cursor: not-allowed; border-color: #d9d9d9; color: #00000040; } .prev-page span, .next-page span, .first-page span, .last-page span { display: inline-block; transform: scale(.5, 1.2) translateY(-1px); min-width: 20px; } .left-more-page span, .right-more-page span { position: relative; display: inline-block; width: 100%; height: 100%; } .left-more-page span:after, .right-more-page span:after { position: absolute; content: '•••'; width: 100%; height: 100%; left: 0; top: 0; font-size: 12px; } .left-more-page:hover span:after { content: '<<'; transform: scale(.5, 1.2); } .right-more-page:hover span:after { content: '>>'; transform: scale(.5, 1.2); }
转载请说明注明作者: 书源