给Gatsby添加标签功能和分类功能(基础版)

首先

本文是https://tech-blog.yoshikiohashi.dev/posts/start-gatsby-blog-add-tags这篇博客文章的转载。

这篇文章是基于一种叫Gatsby的无头CMS技术构建的。本次我们将以“适合初学者”的前提来按以下结构来创建文章。

    • Gatsby始めるまで

 

    • GatsbyにShare機能、OGPタグをつける

 

    • タグ機能、カテゴリ機能をつける(基礎編)

 

    • タグ機能、カテゴリ機能をつける(応用編)

 

    • GatsbyにTableOfContents(目次)をつける

 

    DarkModeをつける

这个内容

这次我们将要实现WordPress的标签功能和分类功能部分。你可能会问,它们不是默认就已经实现了吗?是的,标准模板中并没有实现这些功能。因此,最好选择一个带有这些功能的模板,而不是自行实现。

以下是推薦的範本。

在实施前

首先阅读这篇文章。它在GatsbyJS官方网站上详细介绍了如何给标签打上标记。

步骤

    1. 给markdown文件添加标签

 

    1. 创建GraphQL查询以获取所有标签

 

    1. 创建标签页面模板(/tag/{tag})

 

    1. 使用创建的模板,在gatsby-node.js中渲染页面

 

    创建标签索引页面以显示所有标签(/tags)

1. 在Markdown文件中添加标签。

没有标签的Markdown文件。如果没有的话需要添加标签。

---
title: "A Trip To the Zoo"
---

I went to the zoo today. It was terrible.

我在tags下新增了一個項目。由於可能會設定多個標籤,所以我將其定義為一個陣列。除此之外,我們還可以設定字串和數字(因為類別只有單一所以將其設定為字串)。

---
title: "A Trip To the Zoo"
tags: ["animals", "Chicago", "zoos"]
---

I went to the zoo today. It was terrible.

如果在本地环境中运行了gatsby develop命令,重新启动后,Gatsby将能够获取新的项目。

创建一个GraphQL查询来获取所有的标签。

为了确认GraphQL,请在本地运行gatsby develop,并访问http://localhost:8000/___graphql。

应该可以看到如下所示的屏幕。

一旦画面显示出来后,请尝试输入下面的查询内容。

{
  allMarkdownRemark {
    group(field: frontmatter___tags) {
      tag: fieldValue
      totalCount
    }
  }
}

应该能获取到标签列表。

顺便提一下,group()的意思差不多就跟SQL中的GroupBy一样。在这里,我们根据标签项进行分组。

创建标签页模板(/tag/{tag})

让我们将目录配置为 src/template/tags.js 等。

import React from "react"
import PropTypes from "prop-types"

// Components
import { Link, graphql } from "gatsby"

const Tags = ({ pageContext, data }) => {
  const { tag } = pageContext
  const { edges, totalCount } = data.allMarkdownRemark
  const tagHeader = `${totalCount} post${
    totalCount === 1 ? "" : "s"
  } tagged with "${tag}"`

  return (
    <div>
      <h1>{tagHeader}</h1>
      <ul>
        {edges.map(({ node }) => {
          const { slug } = node.fields
          const { title } = node.frontmatter
          return (
            <li key={slug}>
              <Link to={slug}>{title}</Link>
            </li>
          )
        })}
      </ul>
      {/*
              This links to a page that does not yet exist.
              You'll come back to it!
            */}
      <Link to="/tags">All tags</Link>
    </div>
  )
}

Tags.propTypes = {
  pageContext: PropTypes.shape({
    tag: PropTypes.string.isRequired,
  }),
  data: PropTypes.shape({
    allMarkdownRemark: PropTypes.shape({
      totalCount: PropTypes.number.isRequired,
      edges: PropTypes.arrayOf(
        PropTypes.shape({
          node: PropTypes.shape({
            frontmatter: PropTypes.shape({
              title: PropTypes.string.isRequired,
            }),
            fields: PropTypes.shape({
              slug: PropTypes.string.isRequired,
            }),
          }),
        }).isRequired
      ),
    }),
  }),
}

export default Tags

export const pageQuery = graphql`
  query($tag: String) {
    allMarkdownRemark(
      limit: 2000
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { tags: { in: [$tag] } } }
    ) {
      totalCount
      edges {
        node {
          fields {
            slug
          }
          frontmatter {
            title
          }
        }
      }
    }
  }
`

填补

基本上,我們希望src/template/目錄下的JS文件配置上GraphQL。(如果不需要也沒關係。)

使用流程描述,可表达如下图像。

GraphQL == 查询结果 => 模板 == 查询结果 => 组件的各个部分

使用预先设计的模板,通过gatsby-node.js渲染页面。

既然模板页面已经完成,所以只需在进行Gatsby构建时加载标签页面。Gatsby会首先加载指定的URL页面并构建静态页面。

在这个gatsby-node.js文件中,使用GraphQL查询获取结果,并使用for循环生成与标签数量相对应的迭代项,生成到src/templates/tags.js文件中。

const path = require("path")
const _ = require("lodash")

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

  const blogPostTemplate = path.resolve("src/templates/blog.js")
  const tagTemplate = path.resolve("src/templates/tags.js")

  const result = await graphql(`
    {
      postsRemark: allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___date] }
        limit: 2000
      ) {
        edges {
          node {
            fields {
              slug
            }
            frontmatter {
              tags
            }
          }
        }
      }
      tagsGroup: allMarkdownRemark(limit: 2000) {
        group(field: frontmatter___tags) {
          fieldValue
        }
      }
    }
  `)

  // handle errors
  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

  const posts = result.data.postsRemark.edges

  // Create post detail pages
  posts.forEach(({ node }) => {
    createPage({
      path: node.fields.slug,
      component: blogPostTemplate,
    })
  })

  // Extract tag data from query
  const tags = result.data.tagsGroup.group

  // Make tag pages
  tags.forEach(tag => {
    createPage({
      path: `/tags/${_.kebabCase(tag.fieldValue)}/`,
      component: tagTemplate,
      context: {
        tag: tag.fieldValue,
      },
    })
  })
}

创建一个标签索引页面(/tags),用于显示所有标签的列表。

这次我们要创建标签页面。我们将使用之前编写的GraphQL查询从数据库中获取标签列表,并将获取到的结果应用到模板中。

import React from "react"
import PropTypes from "prop-types"

// Utilities
import kebabCase from "lodash/kebabCase"

// Components
import { Helmet } from "react-helmet"
import { Link, graphql } from "gatsby"

const TagsPage = ({
  data: {
    allMarkdownRemark: { group },
    site: {
      siteMetadata: { title },
    },
  },
}) => (
  <div>
    <Helmet title={title} />
    <div>
      <h1>Tags</h1>
      <ul>
        {group.map(tag => (
          <li key={tag.fieldValue}>
            <Link to={`/tags/${kebabCase(tag.fieldValue)}/`}>
              {tag.fieldValue} ({tag.totalCount})
            </Link>
          </li>
        ))}
      </ul>
    </div>
  </div>
)

TagsPage.propTypes = {
  data: PropTypes.shape({
    allMarkdownRemark: PropTypes.shape({
      group: PropTypes.arrayOf(
        PropTypes.shape({
          fieldValue: PropTypes.string.isRequired,
          totalCount: PropTypes.number.isRequired,
        }).isRequired
      ),
    }),
    site: PropTypes.shape({
      siteMetadata: PropTypes.shape({
        title: PropTypes.string.isRequired,
      }),
    }),
  }),
}

export default TagsPage

export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(limit: 2000) {
      group(field: frontmatter___tags) {
        fieldValue
        totalCount
      }
    }
  }
`

分类的实施

分类功能的思想与标签是一样的。标签由多个数组组成,针对一篇文章可以有多个标签;而分类是一个单一项目,对于一篇文章,需要将其作为字符串以Markdown文件的形式进行描述。

实施步骤

    1. 在markdown文件中添加字符串类型的类别

 

    1. 创建GraphQL查询以获取所有类别

 

    1. 创建类别页面模板

 

    1. 使用创建的模板,在gatsby-node.js中渲染页面

 

    创建一个显示所有类别列表的首页

由于实施内容几乎一样,因此省略不写。

总结

这次怎么样?这次有点难吧?如果你对这个博客的源代码感兴趣的话,可以参考一下,因为它是公开的。那么就在下一篇文章见。

请用中国母语解释以下内容,只需要一个选项:

https://github.com/yoshiki-0428/engneer-blog/blob/master/src/templates/tags-list-template.js#L29-L53

广告
将在 10 秒后关闭
bannerAds