返回

对比Vue/React/Angular:手把手教你构建Pagination分页组件

前端

1. 组件总体设计

Pagination分页组件主要由以下几个部分组成:

  • 当前页码
  • 总页数
  • 上一页、下一页按钮
  • 页码列表
  • 跳转到指定页码的输入框

2. Vue实现

在Vue中,我们可以使用<template>标签定义组件的模板,并在<script>标签中定义组件的逻辑。这里我们使用v-for指令来遍历页码列表,并使用v-on:click指令来绑定点击事件。

<template>
  <div class="pagination">
    <button @click="prevPage" :disabled="currentPage <= 1">上一页</button>
    <ul>
      <li v-for="page in pageList" :key="page" :class="{ active: currentPage === page }">
        <a @click="changePage(page)">{{ page }}</a>
      </li>
    </ul>
    <button @click="nextPage" :disabled="currentPage >= totalPages">下一页</button>
    <input type="number" v-model="currentPage" @change="changePage">
  </div>
</template>

<script>
export default {
  props: {
    currentPage: {
      type: Number,
      default: 1
    },
    totalPages: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      pageList: []
    };
  },
  computed: {
    startPage() {
      return Math.max(1, this.currentPage - 2);
    },
    endPage() {
      return Math.min(this.totalPages, this.currentPage + 2);
    }
  },
  watch: {
    currentPage(val) {
      this.updatePageList();
    }
  },
  methods: {
    prevPage() {
      if (this.currentPage > 1) {
        this.currentPage--;
      }
    },
    nextPage() {
      if (this.currentPage < this.totalPages) {
        this.currentPage++;
      }
    },
    changePage(page) {
      if (page >= 1 && page <= this.totalPages) {
        this.currentPage = page;
      }
    },
    updatePageList() {
      this.pageList = [];
      for (let i = this.startPage; i <= this.endPage; i++) {
        this.pageList.push(i);
      }
    }
  }
};
</script>

3. React实现

在React中,我们可以使用useStateuseEffect钩子来管理组件的状态和副作用。这里我们使用map函数来生成页码列表,并使用onClick事件处理函数来绑定点击事件。

import React, { useState, useEffect } from 'react';

const Pagination = ({ currentPage, totalPages }) => {
  const [pageList, setPageList] = useState([]);

  useEffect(() => {
    updatePageList();
  }, [currentPage]);

  const startPage = Math.max(1, currentPage - 2);
  const endPage = Math.min(totalPages, currentPage + 2);

  const updatePageList = () => {
    const newPageList = [];
    for (let i = startPage; i <= endPage; i++) {
      newPageList.push(i);
    }
    setPageList(newPageList);
  };

  const prevPage = () => {
    if (currentPage > 1) {
      setCurrentPage(currentPage - 1);
    }
  };

  const nextPage = () => {
    if (currentPage < totalPages) {
      setCurrentPage(currentPage + 1);
    }
  };

  const changePage = (page) => {
    if (page >= 1 && page <= totalPages) {
      setCurrentPage(page);
    }
  };

  return (
    <div className="pagination">
      <button onClick={prevPage} disabled={currentPage <= 1}>上一页</button>
      <ul>
        {pageList.map((page) => (
          <li key={page} className={currentPage === page ? 'active' : ''}>
            <a onClick={() => changePage(page)}>{page}</a>
          </li>
        ))}
      </ul>
      <button onClick={nextPage} disabled={currentPage >= totalPages}>下一页</button>
      <input type="number" value={currentPage} onChange={(e) => changePage(e.target.value)} />
    </div>
  );
};

export default Pagination;

4. Angular实现

在Angular中,我们可以使用*ngFor指令来遍历页码列表,并使用(click)事件绑定来绑定点击事件。

<div class="pagination">
  <button [disabled]="currentPage <= 1" (click)="prevPage()">上一页</button>
  <ul>
    <li *ngFor="let page of pageList" [class.active]="currentPage === page">
      <a (click)="changePage(page)">{{ page }}</a>
    </li>
  </ul>
  <button [disabled]="currentPage >= totalPages" (click)="nextPage()">下一页</button>
  <input type="number" [(ngModel)]="currentPage" (change)="changePage($event.target.value)">
</div>
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-pagination',
  templateUrl: './pagination.component.html',
  styleUrls: ['./pagination.component.scss']
})
export class PaginationComponent {

  @Input() currentPage: number = 1;
  @Input() totalPages: number;
  pageList: number[] = [];

  ngOnInit(): void {
    this.updatePageList();
  }

  ngOnChanges(): void {
    this.updatePageList();
  }

  get startPage(): number {
    return Math.max(1, this.currentPage - 2);
  }

  get endPage(): number {
    return Math.min(this.totalPages, this.currentPage + 2);
  }

  updatePageList(): void {
    this.pageList = [];
    for (let i = this.startPage; i <= this.endPage; i++) {
      this.pageList.push(i);
    }
  }

  prevPage(): void {
    if (this.currentPage > 1) {
      this.currentPage--;
    }
  }

  nextPage(): void {
    if (this.currentPage < this.totalPages) {
      this.currentPage++;
    }
  }

  changePage(page: number): void {
    if (page >= 1 && page <= this.totalPages) {
      this.currentPage = page;
    }
  }
}

5. 总结

通过对比Vue、React和Angular这三个主流前端框架,我们发现它们在实现Pagination分页组件时都具有相似之处,但也存在一些细微的差异。总的来说,这三个框架都能够帮助我们快速构建出功能强大的Pagination分页组件,我们可以根据自己的喜好和需求选择其中之一。