Gatsby 的 GraphQL 查询 - 具有灵活内容模型的内容设置
GraphQL queries for Gatsby - Contentful setup with a flexible content model
我有一个 gatsby 站点,其中包含 contentful 插件 和 graphql 查询(设置是工作)。
[编辑]
我的 gatsby 设置使用 pageCreate 功能动态提取数据。并填充我的模板组件,即我在下面分享的根 graphql 查询。如果 contentful 上的页面遵循以下查询中给出的结构,我可以使用该设置创建多个页面。
[/编辑]
我的问题是关于我似乎遇到的一个限制,或者我对 grpahql 的了解还不够多,无法理解。
我的高级内容模型 'BasicPageLayout' 包含通过字段 'Section' 对其他内容类型的引用。因此,它在 'BasicPageLayout' 中包含哪些内容类型以及它们的添加顺序方面是灵活的。
根页面查询
export const pageQuery = graphql`
query basicPageQuery {
contentfulBasicPageLayout(pageName: {eq: "Home"}) {
heroSection {
parent {
id
}
...HeroFields
}
section1 {
parent {
id
}
...ContentText
}
section2 {
parent {
id
}
...ContentTextOverMedia
}
section3 {
parent {
id
}
...ContentTextAndImage
}
section4 {
parent {
id
}
...ContentText
}
}
}
内容类型片段都存在于相应的 UI 组件中。
上述查询和设置有效。
现在,我已经 "Home" 进行了硬编码,因为我在创建灵活的可重用查询时遇到了问题。我在创建模型时利用了 contentful 的灵活性,但还没有找到在 graphql 查询中为它创建这种灵活性的方法。
我所知道的:
Graphql 查询在 运行 时间解析,因此需要获取的所有内容都应该在该查询中。不可能是 'dynamic'.
问题: basicPageLayout 中的 'Section' 字段可以 link 任何内容类型。所以我们可以混合和匹配粒度级别的内容类型。如何添加内容类型片段(如 ContentTextAndImage 与 ContentText)以使其适用于该部分实例(查询中的 'Section' 字段)?
换句话说
我希望根查询获取 'Home' 数据,其中可能有 4 个部分,所有类型 - ContentTextOverMedia
以及 'About ' 可能也有 4 个部分但具有交替类型的数据 - ContentText 和 ContentTextAndImage
这是我的目标,因为我想通过在 contentful 上混合匹配内容类型来创建内容(页面),而无需在每次创建新页面时都更新代码。这就是为什么 Contentful 很有用并被首先选中的原因。
我目前的想法:
一个。 运行 两个查询,串联。一个获取每个部分的 parent.id 并保存内容类型信息。第二个使用适当的片段获取数据。
乙。通过 Contentful API 分别获取 basicPageLayouts 内容实例(例如 'Home')的 JSON 文件,并使用该 JSON 文件创建要在每个实例中使用的 graphql 字符串(因此,主页、关于等的不同布局)
这需要更多的实验,不确定它是否可行,也可能比它需要的更复杂。
所以,请分享我正在探索的上述路径或我没有考虑过使用 graphql 或 gatsby 功能的其他解决方案的想法。
这是我关于 SO 的第一个问题,顺便说一句,我花了一些时间来完善它并尝试遵循指南,但请在评论中给我反馈,这样即使你没有答案我也可以改进我的问题。
提前致谢。
如果我理解正确的话,您想根据来自 Contentful 的数据动态创建页面。
您可以使用 Gatsbyjs 节点 API 实现此目的,特别是 createPage
。
在你的 gatsby-node.js
文件中你可以有这样的东西
const fs = require('fs-extra')
const path = require('path')
exports.createPages = ({graphql, boundActionCreators}) => {
const {createPage} = boundActionCreators
return new Promise((resolve, reject) => {
const landingPageTemplate = path.resolve('src/templates/landing-page.js')
resolve(
graphql(`
{
allContentfulBesicPageLayout {
edges {
node {
pageName
}
}
}
}
`).then((result) => {
if (result.errors) {
reject(result.errors)
}
result.data.allContentfulBesicPageLayout.edges.forEach((edge) => {
createPage ({
path: `${edge.node.pageName}`,
component: landingPageTemplate,
context: {
slug: edge.node.pageName // this will passed to each page gatsby create
}
})
})
return
})
)
})
}
现在在你的 src/templates/landing-page.js
import React, { Component } from 'react'
const LandingPage = ({data}) => {
return (<div>Add you html here</div>)
}
export const pageQuery = graphql`
query basicPageQuery($pageName: String!) {
contentfulBasicPageLayout(pageName: {eq: $pageName}) {
heroSection {
parent {
id
}
...HeroFields
}
section1 {
parent {
id
}
...ContentText
}
section2 {
parent {
id
}
...ContentTextOverMedia
}
section3 {
parent {
id
}
...ContentTextAndImage
}
section4 {
parent {
id
}
...ContentText
}
}
}
请注意 $pageName
参数,这是在创建页面时传递给组件上下文的参数。
这样,您最终将创建任意数量的页面。
请注意:代码的反应部分没有经过测试,但我希望你能理解。
更新:
要有一个灵活的查询,而不是将您的内容类型作为单个 ref 字段,您可以有一个名为 sections 的字段,您可以按照您想要的顺序添加您想要的部分。
您的查询将如下所示
export const pageQuery = graphql`
query basicPageQuery($pageName: String!) {
contentfulBasicPageLayout(pageName: {eq: $pageName}) {
sections {
... on ContentfulHeroFields {
internal {
type
}
}
}
}
哈立德
我有一个 gatsby 站点,其中包含 contentful 插件 和 graphql 查询(设置是工作)。
[编辑] 我的 gatsby 设置使用 pageCreate 功能动态提取数据。并填充我的模板组件,即我在下面分享的根 graphql 查询。如果 contentful 上的页面遵循以下查询中给出的结构,我可以使用该设置创建多个页面。 [/编辑]
我的问题是关于我似乎遇到的一个限制,或者我对 grpahql 的了解还不够多,无法理解。
我的高级内容模型 'BasicPageLayout' 包含通过字段 'Section' 对其他内容类型的引用。因此,它在 'BasicPageLayout' 中包含哪些内容类型以及它们的添加顺序方面是灵活的。
根页面查询
export const pageQuery = graphql`
query basicPageQuery {
contentfulBasicPageLayout(pageName: {eq: "Home"}) {
heroSection {
parent {
id
}
...HeroFields
}
section1 {
parent {
id
}
...ContentText
}
section2 {
parent {
id
}
...ContentTextOverMedia
}
section3 {
parent {
id
}
...ContentTextAndImage
}
section4 {
parent {
id
}
...ContentText
}
}
}
内容类型片段都存在于相应的 UI 组件中。 上述查询和设置有效。
现在,我已经 "Home" 进行了硬编码,因为我在创建灵活的可重用查询时遇到了问题。我在创建模型时利用了 contentful 的灵活性,但还没有找到在 graphql 查询中为它创建这种灵活性的方法。
我所知道的: Graphql 查询在 运行 时间解析,因此需要获取的所有内容都应该在该查询中。不可能是 'dynamic'.
问题: basicPageLayout 中的 'Section' 字段可以 link 任何内容类型。所以我们可以混合和匹配粒度级别的内容类型。如何添加内容类型片段(如 ContentTextAndImage 与 ContentText)以使其适用于该部分实例(查询中的 'Section' 字段)?
换句话说 我希望根查询获取 'Home' 数据,其中可能有 4 个部分,所有类型 - ContentTextOverMedia 以及 'About ' 可能也有 4 个部分但具有交替类型的数据 - ContentText 和 ContentTextAndImage
这是我的目标,因为我想通过在 contentful 上混合匹配内容类型来创建内容(页面),而无需在每次创建新页面时都更新代码。这就是为什么 Contentful 很有用并被首先选中的原因。
我目前的想法:
一个。 运行 两个查询,串联。一个获取每个部分的 parent.id 并保存内容类型信息。第二个使用适当的片段获取数据。
乙。通过 Contentful API 分别获取 basicPageLayouts 内容实例(例如 'Home')的 JSON 文件,并使用该 JSON 文件创建要在每个实例中使用的 graphql 字符串(因此,主页、关于等的不同布局) 这需要更多的实验,不确定它是否可行,也可能比它需要的更复杂。
所以,请分享我正在探索的上述路径或我没有考虑过使用 graphql 或 gatsby 功能的其他解决方案的想法。
这是我关于 SO 的第一个问题,顺便说一句,我花了一些时间来完善它并尝试遵循指南,但请在评论中给我反馈,这样即使你没有答案我也可以改进我的问题。 提前致谢。
如果我理解正确的话,您想根据来自 Contentful 的数据动态创建页面。
您可以使用 Gatsbyjs 节点 API 实现此目的,特别是 createPage
。
在你的 gatsby-node.js
文件中你可以有这样的东西
const fs = require('fs-extra')
const path = require('path')
exports.createPages = ({graphql, boundActionCreators}) => {
const {createPage} = boundActionCreators
return new Promise((resolve, reject) => {
const landingPageTemplate = path.resolve('src/templates/landing-page.js')
resolve(
graphql(`
{
allContentfulBesicPageLayout {
edges {
node {
pageName
}
}
}
}
`).then((result) => {
if (result.errors) {
reject(result.errors)
}
result.data.allContentfulBesicPageLayout.edges.forEach((edge) => {
createPage ({
path: `${edge.node.pageName}`,
component: landingPageTemplate,
context: {
slug: edge.node.pageName // this will passed to each page gatsby create
}
})
})
return
})
)
})
}
现在在你的 src/templates/landing-page.js
import React, { Component } from 'react'
const LandingPage = ({data}) => {
return (<div>Add you html here</div>)
}
export const pageQuery = graphql`
query basicPageQuery($pageName: String!) {
contentfulBasicPageLayout(pageName: {eq: $pageName}) {
heroSection {
parent {
id
}
...HeroFields
}
section1 {
parent {
id
}
...ContentText
}
section2 {
parent {
id
}
...ContentTextOverMedia
}
section3 {
parent {
id
}
...ContentTextAndImage
}
section4 {
parent {
id
}
...ContentText
}
}
}
请注意 $pageName
参数,这是在创建页面时传递给组件上下文的参数。
这样,您最终将创建任意数量的页面。
请注意:代码的反应部分没有经过测试,但我希望你能理解。
更新: 要有一个灵活的查询,而不是将您的内容类型作为单个 ref 字段,您可以有一个名为 sections 的字段,您可以按照您想要的顺序添加您想要的部分。 您的查询将如下所示
export const pageQuery = graphql`
query basicPageQuery($pageName: String!) {
contentfulBasicPageLayout(pageName: {eq: $pageName}) {
sections {
... on ContentfulHeroFields {
internal {
type
}
}
}
}
哈立德