我的盖茨比网站需要2个博客模板:
- stories-template.js
- products.template.js
我的故事正在运行故事模板,但是我不确定如何调整和更改gatsby-node + products.template.js中的现有代码,以为产品创建第二个(不同的)模板。
我已经尝试了所有解决方案和过去的问题,但是没有运气。
我在gatsby-node.js中的代码:
const path = require('path');
exports.createPages = ({actions, graphql}) => {
const { createPage } = actions
const postTemplate = path.resolve('src/components/stories-template.js');
return graphql(`
{
allMarkdownRemark {
edges {
node {
html
id
frontmatter {
path
title
author
date
}
}
}
}
}
`).then(res => {
if(res.errors) {
return Promise.reject(res.errors)
}
res.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
})
})
})
}
stories-template.js中的代码:
import React from 'react'
import Layout from '../components/layout'
export default function Template({data}) {
const post = data.markdownRemark
return(<Layout>
<div>
<p>Stories</p>
<br />
<p>{post.frontmatter.title}</p>
<div dangerouslySetInnerHTML={{__html: post.html}} />
</div>
</Layout>
)
}
export const postQuery = graphql`
query BlogPostByPath($path: String!) {
markdownRemark(frontmatter: { path: {eq:$path}}){
html
frontmatter{
path
title
date
author
}
}
}
`
这可行,但是现在我想在products-template.js中为产品创建一个不同的模板。现在,我的产品模板基本上是从我的故事模板中复制并粘贴的。
我一生中似乎无法弄清这一点。
答案 0 :(得分:2)
就像提到的第一条评论一样,这里可能需要更多的上下文,但我会尝试一下。我认为问题在于,无论页面如何,您都在告诉createPage
函数使用postTemplate
模板组件。
Gatsby不会自动读取模板目录或类似目录中的模板,您需要自己添加逻辑。
首先,您需要使用其他模板,例如:
const postTemplate = path.resolve('src/components/stories-template.js');
const productsTemplate = path.resolve('src/components/products-template.js');
然后,您需要在此处决定何时使用productsTemplate
而不是postTemplate
:
createPage({
path: node.frontmatter.path,
component: postTemplate,
})
例如,也许在每个Markdown文件中,您都有template
YAML主题:
createPage({
path: node.frontmatter.path,
component: node.frontmatter.template === 'product' ? productTemplate : postTemplate,
})
这是我在自己的网站上尝试以更通用的方式进行处理的方法。网址结构决定了模板:如果位于/journal
,它将获取日记模板组件。如果位于/shop
,它将获得Shop模板组件。
这可能不足以进入您现有的网站,但希望它可以使您更接近:
const path = require('path')
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
// I created an object to hold multiple templates.
// In this case, my blog posts are at /journal and my
// products are at /shop, so those are the keys I used here.
// You might have a different system for determining what files
// should use what template.
const templates = {
journal: path.resolve('src/templates/stories-template.js'),
shop: path.resolve('src/templates/products-template.js'),
}
// Query for all Markdown “nodes”
// Note I’m using a different GraphQL query, so you’ll need to replace this
// with yours, or see if something with only the minimum requirements like
// this works for you.
return graphql(`
{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
// Create pages from Markdown files
result.data.allMarkdownRemark.edges.forEach(edge => {
let slug = edge.node.fields.slug
// Get the part of the slug we want, ex. journal
let slugKey = slug.split('/')[1]
// If the slug matches a template, use that, otherwise
// fallback to the default journal template.
// You could use your own logic here.
let template = templates[slugKey] || templates['journal']
createPage({
path: slug, // required
component: template,
context: { slug: slug },
})
})
})
}
我敢肯定,使用诺言的方式会有所改善,但否则对我来说效果很好,并为您提供了一种添加更多模板的不错方法。
答案 1 :(得分:0)
@kennethormandy的答案是正确的,它将帮助您添加新的博客模板!
我只想向其中添加一点:如果您已经将每个模板的markdown内容组织到了不同的目录中,那么在每个内容的最前面添加一个template
道具将是多余的。 / p>
每个MarkdownRemark节点都有一个fileAbsolutePath
字段,该字段使您可以根据内容的来源进行过滤。
例如:
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions
const results = await graphql(`
{
allMarkdownRemark {
edges {
node {
fileAbsolutePath
}
// ...other useful fields
}
}
}
`)
if (results.errors) throw results.errors
results.data.allMarkdownRemark.edges.forEach(({ node }) => {
let template
if (node.fileAbsolutePath.includes('/blogs/')) template = path.resolve('path/to/blog/template')
createPage({ ... }) // ...etc
})
}