盖茨比动态 slug

Posted

技术标签:

【中文标题】盖茨比动态 slug【英文标题】:Gatsby dynamic slug 【发布时间】:2021-07-12 13:51:04 【问题描述】:

首先我将展示我拥有的代码,然后解释问题:

我的 gatsby-node.js 上有这个:

const path = require(`path`)
const  createFilePath  = require(`gatsby-source-filesystem`)

exports.onCreateNode = ( node, getNode, actions ) => 
  const  createNodeField  = actions
  if (node.internal.type === `ContetnfulPost`) 
    const slug = createFilePath( node, getNode, basePath: `pages` )
    createNodeField(
      node,
      name: `slug`,
      value: slug,
    )
  

exports.createPages = async ( graphql, actions ) => 
  const  createPage  = actions
  const result = await graphql(`
    query 
      allContentfulPost 
        edges 
          node 
            postTitle
            slug
          
        
      
    
  `)

  const posts = result.data.allContentfulPost.edges

  posts.forEach(( node , index) => 
    createPage(
      path: `$node.slug`,
      component: path.resolve(`./src/templates/blogPost.js`),
      context: 
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      ,
    )
  )

然后我在 2 个地方查询博客文章:一个像这样的博客页面:

blog.js页面:

function Blog() 
  return (
    <Layout>
      <SEO title="Blog Page" />
      <StaticQuery
        query=graphql`
          query blogQuery 
            allContentfulPost 
              edges 
                node 
                  slug
                  postTitle
                  postImage 
                    file 
                      url
                      fileName
                    
                  
                  postContent 
                    postContent
                  
                  postDate
                
              
            
          
        `
        render=data => (
          <ul>
            data.allContentfulPost.edges.map(( node ) => 
              return (
                <BlogPostsContainer>
                  <Link to=`$node.slug`>
                    <BlogPostImage src=node.postImage.file.url />
                    <PostTitle>node.postTitle</PostTitle>
                  </Link>
                </BlogPostsContainer>
              )
            )
          </ul>
        )
      />
    </Layout>
  )

另一个是我用来在主页上显示我的一些帖子的反应组件:

BlogSection.js

function BlogSection() 
  return (
    <BlogSectionWrapper>
      <StaticQuery
        query=graphql`
          query homeBlogQuery 
            allContentfulPost(limit: 2) 
              edges 
                node 
                  slug
                  postTitle
                  postImage 
                    file 
                      url
                      fileName
                    
                  
                  postContent 
                    postContent
                  
                  postDate
                
              
            
          
        `
        render=data => (
          <ul>
            data.allContentfulPost.edges.map(( node ) => 
              return (
                <HomePostsContainer>
                  <Link to=`$node.slug`>
                    <HomePostImage src=node.postImage.file.url />
                    <PostTitle>node.postTitle</PostTitle>
                  </Link>
                </HomePostsContainer>
              )
            )
          </ul>
        )
      />
      <ButtonWrapper></ButtonWrapper>
      <FlatButton
        item=
          title: "See all posts",
          icon: "/images/icons/book.svg",
          link: "/blog",
        
      />
    </BlogSectionWrapper>
  )

现在的问题是,当我从主页(从BlogSection.js 组件呈现的)点击博客文章时,URL 通常是http://localhost:8000/test-post

但是当我从博客页面(从blog.js 文件呈现)中单击帖子时,URL 变为http://localhost:8000/blog/test-post

我还在每个帖子上添加了 PrevNext 按钮,当我点击它们时,它只是在 URL 中附加了 slug,例如当我在 http://localhost:8000/test-post 并点击 Next 时,它变为http://localhost:8000/test-post/test-post2

如何保留 URL 以仅显示帖子 slug 或者可能为所有帖子添加 /blog 前缀,而与我点击它的位置无关?

我在gatsby-node.js 文件上试过这个,但它不起作用:

posts.forEach(( node , index) => 
    createPage(
      path: `/blog/$node.slug`, //<===== THIS LINE
      component: path.resolve(`./src/templates/blogPost.js`),
      context: 
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      ,
    )
  )

【问题讨论】:

【参考方案1】:

您的动态帖子是在localhost:8000/:post-slug 而不是/blog/:post-slug 下创建的,原因是:

  path: `$node.slug`,

所以,第一步是添加以下内容(到目前为止您已经尝试过):

posts.forEach(( node , index) => 
    createPage(
      path: `/blog/$node.slug`, 
      component: path.resolve(`./src/templates/blogPost.js`),
      context: 
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      ,
    )
  )

之后,请记住,所有不以 / 为前缀的链接都将连接到当前 URL,就像标准锚点(&lt;a&gt; 标记)一样。只需在 slug 的开头添加 / 就可以了。这就解释了这个问题:

我还在每个帖子上添加了 Prev 和 Next 按钮,当我点击 他们,它只是在 URL 中附加 slug,例如当我在 http://localhost:8000/test-post 然后点击下一步,就变成了 http://localhost:8000/test-post/test-post2.

现在,例如,如果您想从主页转到特定帖子,则需要将 /blog 添加到 URL,因为它不是帖子 slug 的一部分:

function BlogSection() 
  return (
    <BlogSectionWrapper>
      <StaticQuery
        query=graphql`
          query homeBlogQuery 
            allContentfulPost(limit: 2) 
              edges 
                node 
                  slug
                  postTitle
                  postImage 
                    file 
                      url
                      fileName
                    
                  
                  postContent 
                    postContent
                  
                  postDate
                
              
            
          
        `
        render=data => (
          <ul>
            data.allContentfulPost.edges.map(( node ) => 
              return (
                <HomePostsContainer>
                  <Link to=`/blog/$node.slug`>
                    <HomePostImage src=node.postImage.file.url />
                    <PostTitle>node.postTitle</PostTitle>
                  </Link>
                </HomePostsContainer>
              )
            )
          </ul>
        )
      />
      <ButtonWrapper></ButtonWrapper>
      <FlatButton
        item=
          title: "See all posts",
          icon: "/images/icons/book.svg",
          link: "/blog",
        
      />
    </BlogSectionWrapper>
  )

注意&lt;Link to=`/blog/$node.slug`&gt;。对blog.js 模板执行相同的操作。

之前的行为在 blog.js 中有效,因为路径不是相对的,它将 post slug 连接到当前 URL (/blog),但没有指向 /blog

要解决更多问题,请检查所有slug 并添加/(如果需要)以避免连接问题。

总结:

gatsby-node.js中创建/blog/:post-slug下的动态帖子:这将生成/blog下的所有帖子 将所有链接指向/blog/:post-slug,无论来源网址如何(要发布的主页等)。 在指向帖子的所有链接的开头添加一个斜杠 (/),以避免 URL 问题的串联和相关性。相同的解决方法适用于下一个和上一个按钮。

【讨论】:

感谢@Ferran,它工作正常。所以如果我想从 Contentful 添加另一个内容模型,比如说 Portfolio,我是否必须复制 gatsby-node.js 中的代码并查询投资组合架构?或者还有另一个代码更少的技巧? 您将需要使用多个查询实例。检查***.com/a/64594951/5585371 你能检查一下这个也请:***.com/questions/67248328/…

以上是关于盖茨比动态 slug的主要内容,如果未能解决你的问题,请参考以下文章

盖茨比动态样式在生产版本中不起作用

盖茨比创建页面

如何在反应盖茨比中映射此 JSON 文件

盖茨比插件图像 | <StaticImage /> 不显示图片

不同的重写动态 slug 被视为重复

如何设置动态路由以在 CodeIgniter 中使用 slug?