简体   繁体   English

如何在'gatsby-node'中使用不同的模板创建多个页面?

[英]how to create multiple pages using different templates in 'gatsby-node'?

i'm new to gatsby and trying to programatically create pages using different templates, but I'm struggling with that.我是 gatsby 的新手,并尝试使用不同的模板以编程方式创建页面,但我正在为此苦苦挣扎。

I have two different pages (landing & press), both written in mdx files, that need different routes and templates when being created programmatically.我有两个不同的页面(登陆和新闻),都是用 mdx 文件编写的,在以编程方式创建时需要不同的路由和模板。

my landing works good, but i failed to add the "press" page.我的登陆效果很好,但我未能添加“新闻”页面。 everything i tried didn't work.我试过的一切都不起作用。

for information, i have a templateKey 'press' and 'landing' in each frontmatter of my markdown files.有关信息,我在降价文件的每个前端都有一个 templateKey 'press' 和 'landing'。

Here is my gatsby-node file :这是我的 gatsby-node 文件:

const path = require("path");
const { createFilePath } = require("gatsby-source-filesystem");
const { fmImagesToRelative } = require("gatsby-remark-relative-images");

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

  const landingTemplate = path.resolve("src/templates/landing.js");
  // const pressTemplate = path.resolve("./src/templates/press.js");

  return graphql(`
    {
      allMarkdownRemark(limit: 1000) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              templateKey
              locale
            }
          }
        }
      }
    }
  `).then((result) => {
    if (result.errors) {
      result.errors.forEach((e) => console.error(e.toString()));
      return Promise.reject(result.errors);
    }

    const posts = result.data.allMarkdownRemark.edges;

    posts.forEach((edge) => {
      const id = edge.node.id;
      createPage({
        path: edge.node.fields.slug,
        component: landingTemplate,
        context: {
          locale: edge.node.frontmatter.locale,
          id,
        },
      });
    });
  });
};

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions;
  fmImagesToRelative(node); // convert image paths for gatsby images

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode });
    createNodeField({
      name: `slug`,
      node,
      value,
    });
  }
};

here is my query in graphiQL这是我在 graphiQL 中的查询

Thank you in advance for any assistance that you may be able to give me !预先感谢您为我提供的任何帮助!

You have to make two different queries to get all your press and all landing data (filtering by each templateKey ).您必须进行两个不同的查询才能获取所有新闻和所有登陆数据(按每个templateKey过滤)。 Once you have the different populated objects you need to call for each object the createPage API to create pages and pass each template value.拥有不同的填充对象后,您需要为每个对象调用createPage API 以创建页面并传递每个模板值。 It should look like:它应该看起来像:

const path = require("path");
const { createFilePath } = require("gatsby-source-filesystem");
const { fmImagesToRelative } = require("gatsby-remark-relative-images");

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

  const landingTemplate = path.resolve("src/templates/landing.js");
  const pressTemplate = path.resolve("./src/templates/press.js");

  const postQuery = await graphql(`
    {
      allMarkdownRemark(
      limit: 1000
      filter: { frontmatter: { templateKey: { eq: "press" }}},
      ) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              templateKey
              locale
            }
          }
        }
      }
    }
  `).then((result) => {
    if (result.errors) {
      result.errors.forEach((e) => console.error(e.toString()));
      return Promise.reject(result.errors);
    }
    

    const posts = postQuery.data.allMarkdownRemark.edges;

    posts.forEach((edge) => {
      const id = edge.node.id;
      createPage({
        path: edge.node.fields.slug,
        component: pressTemplate,
        context: {
          locale: edge.node.frontmatter.locale,
          id,
        },
      });
    });
  });

  const landingQuery = await graphql(`
    {
      allMarkdownRemark(
      limit: 1000
      filter: { frontmatter: { templateKey: { eq: "landing" }}},
      ) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              templateKey
              locale
            }
          }
        }
      }
    }
  `).then((result) => {
    if (result.errors) {
      result.errors.forEach((e) => console.error(e.toString()));
      return Promise.reject(result.errors);
    }


    const landings = landingQuery.data.allMarkdownRemark.edges;

    landings.forEach((edge) => {
      const id = edge.node.id;
      createPage({
        path: edge.node.fields.slug,
        component: landingTemplate,
        context: {
          locale: edge.node.frontmatter.locale,
          id,
        },
      });
    });
  });
  
};

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions;
  fmImagesToRelative(node); // convert image paths for gatsby images

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode });
    createNodeField({
      name: `slug`,
      node,
      value,
    });
  }
};

Your mistake was that you were returning your GraphQL query and that limit your capability to create new queries.您的错误是您返回了 GraphQL 查询,这限制了您创建新查询的能力。 Note that I've also added a promise-based approach, with an async and await functions in order to optimize the queries and the timings.请注意,我还添加了一种基于async的方法,带有asyncawait函数以优化查询和计时。

Without knowing your data structure I've duplicated the query changing the templateKey value, of course, you will need to customize the data that you want to gather for each template and the data you want to pass via context API.在不知道您的数据结构的情况下,我复制了更改templateKey值的查询,当然,您需要自定义要为每个模板收集的数据以及要通过上下文 API 传递的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM