首页 文章

Gatsby的GraphQL查询 - 使用灵活的内容模型进行内容设置

提问于
浏览
2

我有一个带有 contentful plugingraphql queriesgatsby 网站(设置正常) .

[编辑]我的gatsby设置使用pageCreate功能动态提取数据 . 并填充我的模板组件,我在下面分享的根graphql查询 . 如果内容上的页面遵循以下查询中给出的结构,我可以使用设置创建多个页面 . [/编辑]

我的问题是关于我似乎遇到的限制,或者只是不知道足够的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”硬编码,因为我在创建灵活的可重用查询时遇到了麻烦 . 我在创建模型时充分利用了内容的灵活性,但还没有找到一种方法来为它创建graphql查询的灵活性 .

What I do know: Graphql查询在运行时解析,因此需要获取的所有内容都应该在该查询中 . 它可以't be '动态' .

Issue: basicPageLayout中的'Section'字段可以链接到任何内容类型 . 因此,我们可以混合和匹配粒度级别的内容类型 . 如何添加内容类型片段(如ContentTextAndImage vs ContentText),以便它适用于该部分实例(查询中的'Section'字段)?

In other words I 'd like the root query to get '主页' data which might have 4 sections, all of type - ContentTextOverMedia as well as '关于'可能包含4个部分但具有交替类型的数据 - ContentText和ContentTextAndImage

这是我的目标,因为我想通过在内容上混合匹配内容类型来创建内容(Pages),而无需在每次创建新页面时更新代码 . 这就是为什么Contentful很有用并且首先被选中的原因 .

My ideas so far:

A.串联运行两个查询 . 一个获取每个部分的parent.id并保存内容类型信息 . 第二次使用适当的片段获取数据 .

B.通过Contentful API分别获取basicPageLayouts内容实例的JSON文件(例如'Home'),并使用该JSON文件创建要在每个实例中使用的graphql字符串(因此,Home,About等的不同布局这需要更多的实验,不确定它是否可行,也可能比它需要的更复杂 .

所以,请分享我正在探索的上述路径的想法或我没有考虑使用graphql或gatsby功能的其他解决方案 .

这是我关于SO btw的第一个问题,我花了一些时间来完善它并试图遵循指南,但请在评论中给我反馈,这样即使你没有我的问题的答案,我也可以改进 . 提前致谢 .

1 回答

  • 3

    如果我理解正确,您希望根据来自Contentful的数据动态创建页面 .

    您可以使用Gatsbyjs Node 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 param是创建页面时传递给组件上下文的内容 . 这样,您最终将创建任意数量的页面 . 请注意:代码的反应部分没有经过测试,但我希望你能得到这个想法 .

    Update :要获得灵活的查询,而不是将内容类型作为单个引用字段,您可以有一个名为sections的字段,并且可以按所需顺序添加所需的部分 . 您的查询将如下所示

    export const pageQuery = graphql`
        query basicPageQuery($pageName: String!) {
        contentfulBasicPageLayout(pageName: {eq:  $pageName}) {
           sections {
             ... on ContentfulHeroFields {
               internal {
                  type
            }
        }
    }
    

    }

    哈立德

相关问题