You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:43:51