用于生成布局的 Gatsby 动态路由 URL

Gatsby Dynamic Routing URL for Generating Layouts

所以我用这段代码生成条件布局:

exports.onCreatePage = ({ page, actions }) => {
  const { createPage } = actions;

  if (page.path.match(/about/)) {
    page.context.layout = "special";
    createPage(page);
  }

  if (page.path.match(/projects/)) {
    page.context.layout = "projectsPage";
    createPage(page);
  }
};

我想更改 page.path.mathch(/projects/TO ALL PROJECT SLUGS/) 但我不能'没有写出正确的路径语法。

有谁知道如何获取 /projects/ 之后的所有路径?

这是完整的gatsby.node.js

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

exports.onCreatePage = ({ page, actions }) => {
  const { createPage } = actions;

  if (page.path.match(/about/)) {
    page.context.layout = "special";
    createPage(page);
  }

  if (page.path.match(/projects\/([^\/]+$)/)) {
    page.context.layout = "projectsPage";
    createPage(page);
  }
};

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

exports.createPages = async function ({ graphql, actions }) {
  const { data } = await graphql(`
    query Projects {
      allMarkdownRemark {
        nodes {
          frontmatter {
            slug
          }
        }
      }
    }
  `);

  data.allMarkdownRemark.nodes.forEach((node) => {
    const slug = node.frontmatter.slug;
    actions.createPage({
      path: "/projects/" + slug,
      component: path.resolve("./src/templates/project-details.js"),
      context: { slug: slug },
    });
  });
};

这是我的模板:

import React from "react";
import { AnimatePresence, motion } from "framer-motion";
import Navbar from "../components/Navbar/Navbar";
import Footer from "../components/Footer/Footer";
import FooterAbout from "../components/Footer/FooterAbout";

const duration = 0.5;

const variants = {
  initial: {
    opacity: 0,
  },
  enter: {
    opacity: 1,
    transition: {
      duration: duration,
      delay: duration,
      when: "beforeChildren",
    },
  },
  exit: {
    opacity: 0,
    transition: { duration: duration },
  },
};

export const Layout = ({ children, location, pageContext }) => {
  if (pageContext.layout === "projectsPage") {
    return (
      <main className="bg-black ">
        <AnimatePresence>
          <motion.main
            key={location.pathname}
            variants={variants}
            initial="initial"
            animate="enter"
            exit="exit"
            className="opacity-loader"
          >
            {children}
          </motion.main>
        </AnimatePresence>
      </main>
    );
  }
  if (pageContext.layout === "special") {
    return (
      <main className="bg-black ">
        <Navbar />
        <AnimatePresence>
          <motion.main
            key={location.pathname}
            variants={variants}
            initial="initial"
            animate="enter"
            exit="exit"
            className="opacity-loader"
          >
            {children}
          </motion.main>
        </AnimatePresence>
        <FooterAbout />
      </main>
    );
  }
  return (
    <main className="bg-black ">
      <Navbar />
      <AnimatePresence>
        <motion.main
          key={location.pathname}
          variants={variants}
          initial="initial"
          animate="enter"
          exit="exit"
          className="opacity-loader"
        >
          {children}
        </motion.main>
      </AnimatePresence>
      <Footer />
    </main>
  );
};

export default Layout;

我好像遗漏了什么,它接受 (/projects/) 路径但不接受 (/projects/([^/]+$)/)。

为了更清楚,我只想禁用不在 /projects/ 页面中的项目的子目录页面中的布局。

您可以使用以下正则表达式:

projects\/([^\/]+$)

这将匹配 /projects/ 之后的所有内容。所以:

  if (page.path.match(/projects\/([^\/]+$)/)) {
    page.context.layout = "projectsPage";
    createPage(page);
  }

我添加了一个沙箱来测试所有场景:https://regex101.com/r/eQRJb4/1

或者,您可以尝试 gatsby-plugin-create-client-paths 自动完成完全相同的工作。在你的情况下:

{
  resolve: `gatsby-plugin-create-client-paths`,
  options: { prefixes: [`/projects/*`] },
},

您可以像这样更轻松地获得相同的结果:

  data.allMarkdownRemark.nodes.forEach((node) => {
    const slug = node.frontmatter.slug;
    actions.createPage({
      path: "/projects/" + slug,
      component: path.resolve("./src/templates/project-details.js"),
      context: { slug: slug, layout: "projectsPage" },
    });
  });