如何使用 Gatsby 显示图片和 markdown 文件的文件夹

Posted

技术标签:

【中文标题】如何使用 Gatsby 显示图片和 markdown 文件的文件夹【英文标题】:How to use Gatsby to display a folder of images and markdown files 【发布时间】:2021-03-04 05:37:23 【问题描述】:

所以我对 Gatsby、react、GraphQL 等非常陌生。过去我使用纯 CSS、htmljavascript 来制作我的网站。虽然,我对盖茨比和它的功能很感兴趣,所以我决定挑战自己并学习它。

我正在为自己建立一个投资组合网站,并且为了便于更新,我希望能够通过创建新文件夹、运行构建脚本并将构建的站点放入我的 FTP 来添加新项目。

这就是我的项目文件夹结构的设置方式:

-src
--projects
---1-daido-moriyama
----1-dm-frontcover.jpg
----2-dm-spread.jpg
----3-dm-backcover.jpg
----project-metadata.md
[...]
---2-lunch-from-a-care-package
----1-lf-wordmark.png
----2-lf-logo.png
----3-lf-poster.jpg
----project-metadata.md
[...]

该站点是一个页面,因此无需为每个项目创建新页面。我只是将它们分类到编号的文件夹中,因为这对我自己来说是最容易更新的。

理想情况下,我想从每个项目的 markdown 文件中获取标题和描述,并将标题放在 h3 中,将描述放在 ap 中,然后将图像显示在 div 中,样式化后将成为轮播。

Mockup of the design

My current progress

我一直在运行一些测试,并且能够使用 allMarkdownRemark 访问降价文件,并使用 allImageSharp 访问图像。这很 hacky,但它有效,唯一的问题是它显示了 所有 图像,而不仅仅是每个项目所需的图像。比如说,我在一个项目中有 8 张图片,在另一个项目中有 5 张,它将显示所有 13 张图片。

有没有办法做我想要对 Gatsby 做的事情?还是我应该放弃并回到杰基尔……

gatsby-config.js:

module.exports = 
  siteMetadata: 
    title: 'J.C.R.'
  ,
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass',
    
      resolve: 'gatsby-source-filesystem',
      options: 
        name: 'projects',
        path: `$__dirname/src/projects/`
      
    ,
    'gatsby-transformer-remark',
    'gatsby-transformer-sharp',
    'gatsby-plugin-sharp',
    `@dream-bit-de/gatsby-plugin-better-page-tree`
  ]

gatsby-node.js:

const path = require('path')

module.exports.onCreateNode = ( node, actions) => 
    const createNodeField = actions

    if (node.internal.type === 'MarkdownRemark') 
        const slug = path.basename(path.dirname(node.fileAbsolutePath, '.md'))
        createNodeField(
            node,
            name: 'slug',
            value: slug
        )
    

工作组件:

import React from 'react'
import  graphql, useStaticQuery  from 'gatsby'
import Img from 'gatsby-image'

const Work = () => 
    const data = useStaticQuery(graphql`
        query 
            allMarkdownRemark(
                sort:  order: ASC, fields: [frontmatter___position]
            ) 
            edges 
                node 
                    frontmatter 
                        title
                        description
                    
                    fields 
                        slug
                    
                
            
            
            allFile (
            filter:  
                ext: eq: ".jpg"
            ,
            sort:  
                order: ASC, 
                fields: [relativePath]
            
            ) 
                edges 
                node 
                    relativePath
                    relativeDirectory
                    name
                    ext
                    id
                    base
                
            
            
        
    `)

    console.log(data)
    return (
        <div id="work">
            <ol>
                data.allMarkdownRemark.edges.map((edge) => 
                    return (
                        <li class=edge.node.fields.slug>
                            <h3>edge.node.frontmatter.title</h3>
                            <p>edge.node.frontmatter.description</p>
                            data.allFile.edges.map((edge) => 
                                return (
                                    <img src=`../projects$edge.node.relativeDirectory/$edge.node.name-$edge.node.base$edge.node.ext`></img>
                                )
                            )
                        </li>
                    )
                )
            </ol>
        </div>
    )


export default Work

index.js:

import React from 'react'
import Head from '../components/head'
import Info from '../components/info'
import Work from '../components/work'
import '../styles/index.scss'

const indexPage = () => 
  return (
    <div>
      <Head/>
      <Info/>
      <Work/>
    </div>
  )


export default indexPage

【问题讨论】:

【参考方案1】:

我应该深入研究项目以充分了解如何直接使用 graphql 查询来处理它,但一个简短的解决方法是过滤掉与项目无关的图像。

 data.allFile.edge0s.filter((item) => item.name.includes(edge.node.frontmatter.id).map((edge) => 
    return (
   <img src=`../projects$edge.node.relativeDirectory/$edge.node.name-$edge.node.base$edge.node.ext`></img>
)
)

您需要在与项目相关的文件的名称上添加一个特定的 ID,以便在获取它们时过滤掉不相关的文件。

为了更好,您可以格式化您的 imageSchema 并添加一个特定的属性来处理这种情况,这样您就不需要格式化图像名称,然后您可以使用 item.myProperty === 而不是 .includes() myCustomSchemaProperty。

【讨论】:

【参考方案2】:

这比您迄今为止尝试的要容易得多。我建议使用gatsby-image,因为当您添加以下内容时,所有图像都属于 Gatsby 生态系统:


  resolve: 'gatsby-source-filesystem',
  options: 
    name: 'projects',
    path: `$__dirname/src/projects/`
  
,

Gatsby 将在内部解析 /src/projects/ 中的所有内容,并创建节点以使架构可用于 GraphQL,因此:


  allFile(filter: extension: eq: "jpg") 
    edges 
      node 
        childImageSharp
          fluid
            ...GatsbyImageSharpFluid
          
        
      
    
  

然后在你的组件中:

data.allFile.edges.map((edge) => 
   return <Img fluid=edge.childImageSharp.fluid />
)

【讨论】:

以上是关于如何使用 Gatsby 显示图片和 markdown 文件的文件夹的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Gatsby 显示 Contentul 图像

如何使用 gatsby-image 显示新添加的图像文件?

为啥我的一张图片没有显示在 Gatsby 页面上?

如何使用 gatsby-image 显示图像而不进行裁剪?

如何在我的 Gatsby 博客网站中有效地显示 GIF 图像?

如何在 Gatsby 静态图像组件上添加叠加层?