Astro实现分页

发布于 #Astro

为需要分页的page创建对应文件

例如创建archives/[…page].astro

使用paginate函数返回一个page。

export async function getStaticPaths({ paginate }: { paginate: Function }) {
  const posts = await getCollection("blog");
  posts.sort((a, b) => {
    return b.data.pubDate.getTime() - a.data.pubDate.getTime();
  });
  return paginate(posts, {
    pageSize: config.paginate,
  });
}

type Props = {
  page: {
    data: CollectionEntry<"blog">[];
    url: {
      prev: string;
      next: string;
    };
    currentPage: number;
    lastPage: number;
    total: number;
  };
};
const { page } = Astro.props;

根据当前页和总页数计算分页按钮

从 page中渲染对应的分页按钮,创建一个对应的分页器函数,返回page number list。

我指定了中心渲染最大的页码:maxLinks

const renderPaginator = (
  totalPages: number,
  currentPage: number,
  href: string,
  maxLinks: number
) => {
  const paginationLinks: any[] = [];

  // 计算分页器的起始页码和结束页码
  let startPage: number, endPage: number;
  if (totalPages <= maxLinks) {
    startPage = 1;
    endPage = totalPages;
  } else {
    let halfmaxLinks = Math.floor(maxLinks / 2);
    startPage = Math.max(1, currentPage - halfmaxLinks);
    endPage = Math.min(totalPages, currentPage + halfmaxLinks);
    if (endPage - startPage < maxLinks - 1) {
      if (currentPage <= halfmaxLinks) {
        endPage = Math.min(maxLinks, totalPages);
      } else if (currentPage >= totalPages - halfmaxLinks) {
        startPage = Math.max(totalPages - maxLinks + 1, 1);
      }
    }
  }

  // 如果起始页码大于1,添加"1..."按钮
  if (startPage > 1) {
    paginationLinks.push({ page: 1, isActive: false, href });
    if (startPage > 2) {
      paginationLinks.push({ page: "···", isActive: false, href: "#" });
    }
  }

  // 添加页码按钮
  for (let page = startPage; page <= endPage; page++) {
    paginationLinks.push({
      page,
      isActive: page === currentPage,
      href: page > 1 ? `${href}/${page}` : `${href}`,
    });
  }

  // 如果结束页码小于总页数,添加"...n"按钮
  if (endPage < totalPages) {
    if (endPage < totalPages - 1) {
      paginationLinks.push({ page: "···", isActive: false, href: "#" });
    }
    paginationLinks.push({
      page: totalPages,
      isActive: false,
      href: `${href}/${totalPages}`,
    });
  }

  return paginationLinks;
};

const paginationLinks = renderPaginator(last, current, url, paginate_max_links);

然后从这个数组渲染对应的page number

渲染分页

<ul class="flex flex-row flex-auto justify-around items-center space-x-3">
    {
      previous && (
        <PaginationLink href={previous} title="上一页">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            class="w-5 h-5"
            viewBox="0 0 20 20"
            fill="currentColor"
          >
            <path
              fill-rule="evenodd"
              d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
              clip-rule="evenodd"
            />
          </svg>
        </PaginationLink>
      )
    }
    {
      last > 1 &&
        paginationLinks.map(({ page, isActive, href }) => (
          <PaginationLink href={href} isActive={isActive} title={page}>
            {page}
          </PaginationLink>
        ))
    }
    {
      next && (
        <PaginationLink href={next} title="下一页">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            class="w-5 h-5"
            viewBox="0 0 20 20"
            fill="currentColor"
          >
            <path
              fill-rule="evenodd"
              d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
              clip-rule="evenodd"
            />
          </svg>
        </PaginationLink>
      )
    }
  </ul>

可以参考我这个归档页面的分页。

相关文章