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">
      &nbsp;<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);
}

 转载请说明注明作者: 书源

posted on 2023-09-03 11:39  书源  阅读(104)  评论(0编辑  收藏  举报

导航