javascript - 在 Gatsby 上创建第二个博客模板

标签 javascript node.js gatsby

我正在尝试在我的 Gatsby 网站上创建第二个博客模板。我才刚刚开始学习 Javascript,所以我需要有关 gatsby-node.js 文件的帮助。

我尝试复制每一行函数来创建第二个博客模板,但每次都失败了,所以如果有人可以遍历我的代码并提供正确的函数,那将非常有帮助。

我目前有一个成功运行的“文章”模板。我想创建第二个“项目”模板。

这是我当前的 gatsby-node.js 文件,仅调用“文章”博客模板。


const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');

// Look at every node when it is created
exports.onCreateNode = ({node, getNode, actions}) => {
  // Check for markdown nodes
  const { createNodeField } = actions;
  if(node.internal.type === 'MarkdownRemark') {
    // Create a slug out of the markdown filepath name
    const slug = createFilePath({
      node,
      getNode,
      basePath: 'articles'
    });
    // Add the newly created slug to the node itself
    createNodeField({
      node,
      name: 'slug',
      value: `/article${slug}`
    });
  }
};

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    graphql(`
    {
      allMarkdownRemark {
      edges {
        node {
        fields {
          slug
        }
        }
      }
      }
    }
    `).then(result => {
    result.data.allMarkdownRemark.edges.forEach(({ node }) => {
      createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/article.js`),
      context: {
        // Data passed to context is available in page queries as GraphQL variables.
        slug: node.fields.slug,
      },
      })
    })
    resolve()
    })
  })
  };


如何配置此文件以调用第二个博客模板(“项目”)?

最佳答案

首先,您需要在您获得的 graphql 查询中检索您的文章和项目。您可以使用冒号重命名查询的一部分。我在你的 allMarkdownRemark 之前添加了 articles:。在生成的 JSON 中,allMarkdownRemark 现在将被称为“文章”。您可以在现在遍历“result.data.articles”的 forEach 循环中看到这一点。我还添加了对您想要的“项目”实体的查询。将它们重命名为文章和项目使我们能够轻松地迭代每篇文章和每个项目,并为这些实体创建正确的页面。

projects 查询现在是 articles 查询的副本。实际上,您应该在此处提供一个仅返回项目的查询,但我不知道您在哪里有这些项目。然后为您在其中创建正确页面的项目和文章创建单独的循环。

exports.createPages = ({ graphql, actions }) => {
    const { createPage } = actions

    return new Promise((resolve, reject) => {
        graphql(`{
            articles: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
            projects: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
        }`).then(result => {

            // In this loop we only take the articles returned by the query, and
            // pass them to the src/templates/article.js component.
            result.data.articles.edges.forEach(({ node }) => {
                createPage({
                    // Rather than prepending every slug with '/article' in the
                    // createNodeField call, you can add it here to get more
                    // flexibility, and to allow different types to have different
                    // path prefixes.
                    path: `article/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/article.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            // In this loop we do the same thing, only with the projects this
            // time, and passing them to the project.js component I'm assuming
            // you have. I've prepended the path with 'project/' to separate
            // the projects from the articles.
            result.data.projects.edges.forEach(({ node }) => {
                createPage({
                    path: `project/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/project.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            resolve()
        })
    })
};

我添加了一些缩进,使事情更容易推理。我可能在整个过程中犯了一些语法错误,所以要当心。

我注意到在您的 onCreateNode 调用中,您将每个 Markdown 文件的 slug 设置为“article/${slug}”。如果你的项目也是 markdown 文件,你不应该这样做,因为它也会给你的项目 markdown 文件以 '/article' 开头的 slugs。在上面的代码中,我在 createPage 调用中设置了正确的路径,而不是在 createNodeField 中。

您必须牢记的一件事是,如果您将文章和项目都作为 markdown 文件,您的查询将很难区分它们。我通常解决这个问题的方法是在 frontmatter 中添加一个“类型”字段。因此,在您的情况下,您将添加: type: article 到所有文章的 frontmatter,并将 type: project 添加到所有项目。 frontmatter 部分是 markdown 文件顶部的部分,在三个虚线之间:

---
type: article
name: something
etc, etc...
---

您可以像这样过滤您的 Markdown 文件:

graphql(`query {
      projects: allMarkdownRemark ( filter: {frontmatter: { type: { eq: "project" } } } ) {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }`);

这将只返回项目类型的 Markdown 文件。对你的文章做同样的事情。如果你使用 Netlify CMS,你可以添加一个隐藏字段来自动添加正确的类型来帮助你过滤。

您可能需要考虑将 promise 更改为异步/等待调用。这是可选的,但在我看来,它使事情更容易阅读。在此处查看 Gatsby 的教程 https://www.gatsbyjs.org/tutorial/part-seven/#creating-pages有关 createPages API 中异步/等待的示例。

关于javascript - 在 Gatsby 上创建第二个博客模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58422460/

相关文章:

javascript - 如何在Javascript中打印点击事件

javascript - 在产品页面上输入文本字段而不是组合的下拉列表

javascript - 在 Angularjs 中访问组件/ Controller 之间的对象

Github pages 上的 Gatsby deploy 缺少文件,但在本地看起来不错

javascript - 同构 React 与 Gatsby(静态站点)React

javascript - filter() 返回空数组

javascript - 从 JSON 读取返回未定义

javascript - Node js中唯一的json数据对象

javascript - 如何将 uncrustify 与 atom-beautify 一起使用?

gatsby - Gatsby 中的 DOM 属性不会更新