在Gatsby单篇文章中实现上/下一篇链接的技术问询
实现文章上一篇/下一篇链接的最优方案
不需要手动在frontmatter中添加id字段,Gatsby会自动为每个MDX节点生成唯一id,结合日期排序就能实现上一篇/下一篇链接,以下是两种可行方案:
方案一:组件内处理所有文章数据(推荐,逻辑直观)
修改GraphQL查询,同时获取当前文章和所有其他文章的列表,在组件中通过索引定位前后篇:
1. 更新页面查询
export const query = graphql` query ($id: String) { # 获取当前文章详情,保留原始date用于排序比较 currentPost: mdx(id: {eq: $id}) { frontmatter { title date(formatString: "MMMM D, YYYY") slug date } id } # 获取所有文章,按发布日期倒序排列,排除当前文章 allPosts: allMdx( sort: {frontmatter: {date: DESC}} filter: {id: {ne: $id}} ) { nodes { frontmatter { title slug } id } } } `;
2. 组件内计算前后篇
export default function PostPage({ data }) { const { currentPost, allPosts } = data; const posts = allPosts.nodes; // 找到当前文章在列表中的位置 const currentIndex = posts.findIndex(post => post.id === currentPost.id); // 上一篇:列表中当前文章的前一项(若存在) const prevPost = currentIndex > 0 ? posts[currentIndex - 1] : null; // 下一篇:列表中当前文章的后一项(若存在) const nextPost = currentIndex < posts.length - 1 ? posts[currentIndex + 1] : null; return ( <div className="post-page"> <h1>{currentPost.frontmatter.title}</h1> <p className="post-date">{currentPost.frontmatter.date}</p> {/* 渲染文章内容 */} <div className="post-nav"> {prevPost && ( <a href={`/${prevPost.frontmatter.slug}`}> ← {prevPost.frontmatter.title} </a> )} {nextPost && ( <a href={`/${nextPost.frontmatter.slug}`}> {nextPost.frontmatter.title} → </a> )} </div> </div> ); }
方案二:GraphQL直接筛选前后篇(适合大数量文章)
通过GraphQL的filter和sort直接查询出前后篇,减少前端处理的数据量:
1. 更新页面查询
需要在createPage时将文章的date传入页面context,确保$date变量能被查询获取:
export const query = graphql` query ($id: String, $date: Date) { currentPost: mdx(id: {eq: $id}) { frontmatter { title date(formatString: "MMMM D, YYYY") slug } } # 上一篇:发布时间早于当前文章的最新一篇 prevPost: mdx( filter: {frontmatter: {date: {lt: $date}}, id: {ne: $id}} sort: {frontmatter: {date: DESC}} limit: 1 ) { frontmatter { title slug } } # 下一篇:发布时间晚于当前文章的最早一篇 nextPost: mdx( filter: {frontmatter: {date: {gt: $date}}, id: {ne: $id}} sort: {frontmatter: {date: ASC}} limit: 1 ) { frontmatter { title slug } } } `;
注:需在
gatsby-node.js的createPage方法中,将文章的frontmatter.date添加到context中。
2. 组件中直接使用查询结果
export default function PostPage({ data }) { const { currentPost, prevPost, nextPost } = data; return ( <div className="post-page"> <h1>{currentPost.frontmatter.title}</h1> <p className="post-date">{currentPost.frontmatter.date}</p> {/* 渲染文章内容 */} <div className="post-nav"> {prevPost && ( <a href={`/${prevPost.frontmatter.slug}`}> ← {prevPost.frontmatter.title} </a> )} {nextPost && ( <a href={`/${nextPost.frontmatter.slug}`}> {nextPost.frontmatter.title} → </a> )} </div> </div> ); }
方案优势
- 无需手动维护
id字段,避免人工输入错误 - 依赖Gatsby自动生成的节点
id或文章slug(确保slug唯一)作为标识,可靠性更高 - 排序逻辑可灵活调整(比如按标题、更新时间等)
内容的提问来源于stack exchange,提问作者yansusanto
相关产品推荐
相关产品推荐

