在Gatsby中通过查询变量获取Contentful特定类型节点
在Gatsby中动态查询不同内容类型的节点
完全可以实现!根本不用给每个contentType单独写查询——Gatsby的GraphQL支持动态参数,只要用对方法就能搞定。我给你一步步拆解怎么做:
1. 先在gatsby-node.js里传递内容类型参数
当你生成落地页的时候,把你要查询的contentType作为上下文参数传给模板。比如你要生成songs和blogs的落地页,代码可以这么写:
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; // 列出你需要的所有内容类型 const contentTypes = ["songs", "blogs"]; for (const type of contentTypes) { createPage({ path: `/${type}`, // 页面路径,比如/songs或/blogs component: require.resolve("./src/templates/landing-page.js"), // 你的落地页模板路径 context: { contentType: type, // 把当前类型传给模板 }, }); } };
2. 在模板里用页面查询接收动态参数
注意!StaticQuery不支持动态变量,所以必须用**页面查询(Page Query)**来接收上下文里的contentType。这里分两种常见场景处理:
场景一:本地文件(比如MDX/Markdown)
假设你在gatsby-config.js里给不同内容类型配置了sourceInstanceName(比如songs文件夹对应sourceInstanceName为"songs"),查询可以这么写:
import React from "react"; import { graphql } from "gatsby"; const LandingPage = ({ data }) => { const items = data.allMdx.nodes; return ( <div> <h1>{data.contentType}列表</h1> <ul> {items.map(item => ( <li key={item.id}>{item.frontmatter.title}</li> ))} </ul> </div> ); }; export const query = graphql` query($contentType: String!) { allMdx(filter: { fields: { sourceInstanceName: { eq: $contentType } } }) { nodes { id frontmatter { title } } } } `; export default LandingPage;
场景二:CMS数据源(比如Contentful)
如果用的是Contentful这类CMS,不同内容类型的节点有固定的__typename(比如ContentfulSong、ContentfulBlog),你可以用片段来匹配不同类型的字段:
import React from "react"; import { graphql } from "gatsby"; const LandingPage = ({ data, pageContext }) => { const items = data.allNode.nodes; return ( <div> <h1>{pageContext.contentType}列表</h1> <ul> {items.map(item => ( <li key={item.id}> {item.title} {/* 不同类型的专属字段 */} {item.duration && <span> - {item.duration}分钟</span>} {item.excerpt && <p>{item.excerpt}</p>} </li> ))} </ul> </div> ); }; export const query = graphql` query($contentType: String!) { allNode(filter: { __typename: { eq: $contentType } }) { nodes { id ... on ContentfulSong { title duration } ... on ContentfulBlog { title excerpt } } } } `; export default LandingPage;
这种情况下,你需要把gatsby-node.js里的contentType改成对应的__typename值,比如"ContentfulSong"而不是"songs"。
3. 避坑提醒
- 之前出现语法错误大概率是用了StaticQuery,它不支持动态变量,必须换成Page Query。
- 如果你的节点有自定义的
contentType字段,也可以直接用这个字段做filter,不用依赖__typename或sourceInstanceName,灵活调整就行。
内容的提问来源于stack exchange,提问作者Aaron Austin
相关产品推荐
相关产品推荐

