Javascript 如何创建一个Gatsby页面,按标签/类别显示和过滤所有博客文章

Javascript 如何创建一个Gatsby页面,按标签/类别显示和过滤所有博客文章,javascript,reactjs,gatsby,netlify,netlify-cms,Javascript,Reactjs,Gatsby,Netlify,Netlify Cms,你好,我正在用盖茨比和Netlify CMS建立一个博客。我从盖茨比初学者netlify cms模板开始 我有一个/blog页面,在那里我当前显示了所有帖子以及所有标签的列表。 当用户单击标签时,它当前被重定向到tags/name of tag页面,在该页面上显示所有贴有类似标签的帖子的列表 我想要的是直接过滤/blog页面上的列表。 这样,我就只有一个页面可以按标签显示和过滤博客文章(可能还有术语搜索) 因此标记链接应该重定向到/blog?标记名或类似的内容。 我不知道如何告诉盖茨比创建一个可

你好,我正在用盖茨比和Netlify CMS建立一个博客。我从盖茨比初学者netlify cms模板开始

我有一个
/blog
页面,在那里我当前显示了所有帖子以及所有标签的列表。 当用户单击标签时,它当前被重定向到
tags/name of tag
页面,在该页面上显示所有贴有类似标签的帖子的列表

我想要的是直接过滤
/blog
页面上的列表。 这样,我就只有一个页面可以按标签显示和过滤博客文章(可能还有术语搜索)

因此标记链接应该重定向到
/blog?标记名
或类似的内容。
我不知道如何告诉盖茨比创建一个可以插入
过滤器
值的页面,以便将其传递给页面查询

这就是当前创建
/tags/
页面的方式:

// Tag pages:
    let tags = []
    // Iterate through each post, putting all found tags into `tags`
    posts.forEach((edge) => {
      if (_.get(edge, `node.frontmatter.tags`)) {
        tags = tags.concat(edge.node.frontmatter.tags)
      }
    })
    // Eliminate duplicate tags
    tags = _.uniq(tags)

    // Make tag pages
    tags.forEach((tag) => {
      const tagPath = `/tags/${_.kebabCase(tag)}/`

      createPage({
        path: tagPath,
        component: path.resolve(`src/templates/tags.js`),
        context: {
          tag,
        },
      })
    })
这是我的博客页面查询(我希望能够通过标记进行筛选):

我不知道如何告诉盖茨比用 可以插入
过滤器
值以将其传递到页面 询问

你不能。过滤页面查询中数据的唯一方法是使用上下文传递数据。就像您在标签页中所做的那样:

  createPage({
    path: tagPath,
    component: path.resolve(`src/templates/tags.js`),
    context: {
      tag,
    },
  })
最简单的本地方法是使用
/tag/tag name
页面,该页面旨在按标记名进行过滤,否则,您需要获取URL参数并在JavaScript函数中使用它来过滤页面查询中的所有数据。由于您缺少博客页面的呈现部分。。。类似于这种方法的方法应该有效:

const BlogTemplate=({ data }){
    if(typeof window !== "undefined"){
      const queryString = window.location.search;
      const urlParams = new URLSearchParams(queryString);
      const urlTag= urlParams.get('tag');
      const filteredPosts= data.allMarkdownRemark.edges.node.filter(node=> node.frontmatter.tag.includes(urlTag))
      const loopData= urlParams.has('tag') ? filteredPosts : data
   }
   
return loopData.allMarkdownRemark.edges.node.map(node=> <h1 key={node.title}>{node.title}</h1>)

}
constblogtemplate=({data}){
如果(窗口类型!=“未定义”){
const queryString=window.location.search;
const urlParams=新的URLSearchParams(queryString);
const urlTag=urlParams.get('tag');
const filteredPosts=data.allmarkdownmark.edges.node.filter(node=>node.frontmatter.tag.includes(urlTag))
const loopData=urlParams.has('tag')?filteredPosts:data
}
返回loopData.allMarkdownRemark.edges.node.map(node=>{node.title})
}
注意:当然,根据你的需要调整它,但要有想法

还请注意,您需要将所有窗口逻辑包装在
typeof window!==“未定义”
条件,自

关键部分是根据URL参数的存在来使用
数据
还是您的
过滤器主题
,因此如果它存在,您将需要过滤数据,否则,您需要使用“默认”
数据
(未过滤)

很难猜测代码将如何运行,但是这个想法依赖于根据URL更改可编辑的数据,如果需要,使用一些钩子

根据您的查询,您的博客在博客模板查询中似乎不包含任何
标记
字段,因此您需要添加它以允许
过滤器
循环工作


代码运行后,您需要添加适当的控件,以避免在缺少某个字段时出现代码中断,但思路和路径如下。

到目前为止您做了哪些尝试?我想在从页面查询中获取所有帖子的数组后直接过滤列表,但是我不知道如何从另一个链接触发过滤(比如在另一个页面中单击博客帖子标签)。最好的方法是使用盖茨比的页面节点创建和graphql,但我不知道如何…您的代码作为一个魅力(在适应了我的变量名等之后),谢谢!我得到的唯一错误来自这一行:
const-filteredPosts=data.allmarkdownmark.edges.node.filter(node=>node.frontmatter.tag.includes(urlTag))
应该是
const-filteredPosts=data.allmarkdownmark.edges.node.filter(node=>return-node.frontmatter.tag.includes(urlTag))
因为.filter没有返回对象
const BlogTemplate=({ data }){
    if(typeof window !== "undefined"){
      const queryString = window.location.search;
      const urlParams = new URLSearchParams(queryString);
      const urlTag= urlParams.get('tag');
      const filteredPosts= data.allMarkdownRemark.edges.node.filter(node=> node.frontmatter.tag.includes(urlTag))
      const loopData= urlParams.has('tag') ? filteredPosts : data
   }
   
return loopData.allMarkdownRemark.edges.node.map(node=> <h1 key={node.title}>{node.title}</h1>)

}