盖茨比动态弹头
Gatsby dynamic slug
首先我要展示我的代码,然后解释问题:
我的 gatsby-node.js
:
上有这个
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `ContetnfulPost`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allContentfulPost {
edges {
node {
postTitle
slug
}
}
}
}
`)
const posts = result.data.allContentfulPost.edges
posts.forEach(({ node }, index) => {
createPage({
path: `${node.slug}`,
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
}
然后我在两个地方查询博客 posts:一个是这样的博客页面:
blog.js
页数:
function Blog() {
return (
<Layout>
<SEO title="Blog Page" />
<StaticQuery
query={graphql`
query blogQuery {
allContentfulPost {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<BlogPostsContainer>
<Link to={`${node.slug}`}>
<BlogPostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</BlogPostsContainer>
)
})}
</ul>
)}
/>
</Layout>
)
}
还有一个 React 组件,我用它在主页上显示我的一些 post:
BlogSection.js
function BlogSection() {
return (
<BlogSectionWrapper>
<StaticQuery
query={graphql`
query homeBlogQuery {
allContentfulPost(limit: 2) {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<HomePostsContainer>
<Link to={`${node.slug}`}>
<HomePostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</HomePostsContainer>
)
})}
</ul>
)}
/>
<ButtonWrapper></ButtonWrapper>
<FlatButton
item={{
title: "See all posts",
icon: "/images/icons/book.svg",
link: "/blog",
}}
/>
</BlogSectionWrapper>
)
}
现在的问题是,当我从主页(从 BlogSection.js
组件呈现的那些)单击博客 post 时,URL 通常是 http://localhost:8000/test-post
.
但是当我从博客页面(从 blog.js
文件呈现)单击 post 时,URL 变为 http://localhost:8000/blog/test-post
。
我还在每个 post 上添加了 Prev
和 Next
按钮,当我点击它们时,它只是将 slug 添加到 URL,例如当我在http://localhost:8000/test-post
点击Next
,变成了http://localhost:8000/test-post/test-post2
。
我怎样才能让 URL 只显示 post slug 或为所有 post 加上一个 /blog
前缀独立于我点击的地方是吗?
我在 gatsby-node.js
文件上试过了,但它不起作用:
posts.forEach(({ node }, index) => {
createPage({
path: `/blog/${node.slug}`, //<===== THIS LINE
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
您的动态 post 是在 localhost:8000/:post-slug
而不是在 /blog/:post-slug
下创建的,因为:
path: `${node.slug}`,
因此,第一步是添加以下内容(您目前已尝试过的内容):
posts.forEach(({ node }, index) => {
createPage({
path: `/blog/${node.slug}`,
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
之后,请记住,所有未以 /
为前缀的链接都将连接到当前的 URL,就像标准锚点 (<a>
标签)。只需在 slug 的开头添加一个 /
就可以解决问题。这解释了这个问题:
I also added Prev and Next buttons on each post and when I click on
them, it just appends the slug in the URL, for instance when I'm on
http://localhost:8000/test-post
and click Next, it becomes
http://localhost:8000/test-post/test-post2
.
现在,例如,如果您想从主页转到特定 post,您需要将 /blog
添加到 URL,因为它不是post 子弹的一部分:
function BlogSection() {
return (
<BlogSectionWrapper>
<StaticQuery
query={graphql`
query homeBlogQuery {
allContentfulPost(limit: 2) {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<HomePostsContainer>
<Link to={`/blog/${node.slug}`}>
<HomePostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</HomePostsContainer>
)
})}
</ul>
)}
/>
<ButtonWrapper></ButtonWrapper>
<FlatButton
item={{
title: "See all posts",
icon: "/images/icons/book.svg",
link: "/blog",
}}
/>
</BlogSectionWrapper>
)
}
注意 <Link to={`/blog/${node.slug}`}>
。并用 blog.js
模板做同样的事情。
之前的行为在 blog.js
中有效,因为路径不是相对的,它将 post slug 连接到当前的 URL (/blog
),但不是't 指向 /blog
.
要解决进一步的问题,请检查所有 slug
并添加 /
(如果需要)以避免连接问题。
总结:
- 在
gatsby-node.js
中的 /blog/:post-slug
下创建动态 posts:这将生成 /blog
下的所有 posts
- 将所有链接指向
/blog/:post-slug
,无论来源如何 URL(主页指向 post,等等)。
- 在所有指向 post 的链接的开头添加斜杠 (
/
) 以避免 URL 问题的串联和相关性。相同的解决方法适用于下一个和上一个按钮。
首先我要展示我的代码,然后解释问题:
我的 gatsby-node.js
:
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `ContetnfulPost`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allContentfulPost {
edges {
node {
postTitle
slug
}
}
}
}
`)
const posts = result.data.allContentfulPost.edges
posts.forEach(({ node }, index) => {
createPage({
path: `${node.slug}`,
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
}
然后我在两个地方查询博客 posts:一个是这样的博客页面:
blog.js
页数:
function Blog() {
return (
<Layout>
<SEO title="Blog Page" />
<StaticQuery
query={graphql`
query blogQuery {
allContentfulPost {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<BlogPostsContainer>
<Link to={`${node.slug}`}>
<BlogPostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</BlogPostsContainer>
)
})}
</ul>
)}
/>
</Layout>
)
}
还有一个 React 组件,我用它在主页上显示我的一些 post:
BlogSection.js
function BlogSection() {
return (
<BlogSectionWrapper>
<StaticQuery
query={graphql`
query homeBlogQuery {
allContentfulPost(limit: 2) {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<HomePostsContainer>
<Link to={`${node.slug}`}>
<HomePostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</HomePostsContainer>
)
})}
</ul>
)}
/>
<ButtonWrapper></ButtonWrapper>
<FlatButton
item={{
title: "See all posts",
icon: "/images/icons/book.svg",
link: "/blog",
}}
/>
</BlogSectionWrapper>
)
}
现在的问题是,当我从主页(从 BlogSection.js
组件呈现的那些)单击博客 post 时,URL 通常是 http://localhost:8000/test-post
.
但是当我从博客页面(从 blog.js
文件呈现)单击 post 时,URL 变为 http://localhost:8000/blog/test-post
。
我还在每个 post 上添加了 Prev
和 Next
按钮,当我点击它们时,它只是将 slug 添加到 URL,例如当我在http://localhost:8000/test-post
点击Next
,变成了http://localhost:8000/test-post/test-post2
。
我怎样才能让 URL 只显示 post slug 或为所有 post 加上一个 /blog
前缀独立于我点击的地方是吗?
我在 gatsby-node.js
文件上试过了,但它不起作用:
posts.forEach(({ node }, index) => {
createPage({
path: `/blog/${node.slug}`, //<===== THIS LINE
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
您的动态 post 是在 localhost:8000/:post-slug
而不是在 /blog/:post-slug
下创建的,因为:
path: `${node.slug}`,
因此,第一步是添加以下内容(您目前已尝试过的内容):
posts.forEach(({ node }, index) => {
createPage({
path: `/blog/${node.slug}`,
component: path.resolve(`./src/templates/blogPost.js`),
context: {
slug: node.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === posts.length - 1 ? null : posts[index + 1].node,
},
})
})
之后,请记住,所有未以 /
为前缀的链接都将连接到当前的 URL,就像标准锚点 (<a>
标签)。只需在 slug 的开头添加一个 /
就可以解决问题。这解释了这个问题:
I also added Prev and Next buttons on each post and when I click on them, it just appends the slug in the URL, for instance when I'm on
http://localhost:8000/test-post
and click Next, it becomeshttp://localhost:8000/test-post/test-post2
.
现在,例如,如果您想从主页转到特定 post,您需要将 /blog
添加到 URL,因为它不是post 子弹的一部分:
function BlogSection() {
return (
<BlogSectionWrapper>
<StaticQuery
query={graphql`
query homeBlogQuery {
allContentfulPost(limit: 2) {
edges {
node {
slug
postTitle
postImage {
file {
url
fileName
}
}
postContent {
postContent
}
postDate
}
}
}
}
`}
render={data => (
<ul>
{data.allContentfulPost.edges.map(({ node }) => {
return (
<HomePostsContainer>
<Link to={`/blog/${node.slug}`}>
<HomePostImage src={node.postImage.file.url} />
<PostTitle>{node.postTitle}</PostTitle>
</Link>
</HomePostsContainer>
)
})}
</ul>
)}
/>
<ButtonWrapper></ButtonWrapper>
<FlatButton
item={{
title: "See all posts",
icon: "/images/icons/book.svg",
link: "/blog",
}}
/>
</BlogSectionWrapper>
)
}
注意 <Link to={`/blog/${node.slug}`}>
。并用 blog.js
模板做同样的事情。
之前的行为在 blog.js
中有效,因为路径不是相对的,它将 post slug 连接到当前的 URL (/blog
),但不是't 指向 /blog
.
要解决进一步的问题,请检查所有 slug
并添加 /
(如果需要)以避免连接问题。
总结:
- 在
gatsby-node.js
中的/blog/:post-slug
下创建动态 posts:这将生成/blog
下的所有 posts
- 将所有链接指向
/blog/:post-slug
,无论来源如何 URL(主页指向 post,等等)。 - 在所有指向 post 的链接的开头添加斜杠 (
/
) 以避免 URL 问题的串联和相关性。相同的解决方法适用于下一个和上一个按钮。