Skip to content

分类 / 标签 / 归档

分类 / 标签

分类和标签分为新旧两个版本,主要区别是新版每个分类/标签单独一个页面,旧版则是在同一个页面切换分类/标签。具体的表现形式为:

  • 新版:通过动态路由来实现分类与标签的切换,URL 看起来像动态博客一样,更加优雅

    • /category/文章
    • /category/子文章
    • /tags/短暂的宁静
  • 旧版:通过 query 参数来实现分类与标签的切换,切换速度更快

    • /category?category=文章
    • /category?category=子文章
    • /category?tag=短暂的宁静

无论新旧版本,都需要在的 Frontmatter 中,为文章设置分类标签

yaml
category: 分类 A
tags: 
  - 标签 A
  - 标签 B

新版

分类

创建 category 目录,在文件夹内创建 [category].md [category].paths.ts 两个文件

markdown
---
title: 分类
layout: page
---

<Category />

<script lang="ts" setup>
import { onMounted } from "vue";
import { useData } from "vitepress"

const { params, site } = useData();

onMounted(() => {
  if (params.value?.category && params.value.category !== 'index') {
    document.title = `分类:${params.value.category} | ${site.value.titleTemplate}`;
  }
});
</script>
ts
import fg from 'fast-glob';
import matter from 'gray-matter';

export default {
  async paths() {
    const paths = await fg('posts/**/*.md');
    const categories = new Set<string>();
    const isProd = process.env.NODE_ENV === 'production';

    for (const postPath of paths) {
      const { data } = matter.read(postPath);
      const skip = isProd && (data.draft || data.hidden);

      if (data.category && !skip) {
        categories.add(String(data.category));
      }
    }

    const routePaths = [...categories].map((category) => ({
      params: { category }
    }));

    routePaths.push({ params: { category: 'index' } });

    return routePaths;
  }
};

标签

和分类一样,创建 tags 目录,在文件夹内创建 [tag].md [tag].paths.ts

markdown
---
title: 标签
layout: page
---

<Category type="tag" />

<script lang="ts" setup>
import { onMounted } from "vue";
import { useData } from "vitepress"

const { params, site } = useData();

onMounted(() => {
  if (params.value?.tag && params.value.tag !== 'index') {
    document.title = `标签:${params.value.tag} | ${site.value.titleTemplate}`;
  }
});
</script>
ts
import fg from 'fast-glob';
import matter from 'gray-matter';

export default {
  async paths() {
    const paths = await fg('posts/**/*.md');
    const tags = new Set<string>();
    const isProd = process.env.NODE_ENV === 'production';

    for (const postPath of paths) {
      const { data } = matter.read(postPath);
      const skip = isProd && (data.draft || data.hidden);

      if (Array.isArray(data.tags) && !skip) {
        data.tags.forEach((tag: unknown) => {
          if (tag != null) tags.add(String(tag));
        });
      }
    }

    const routePaths = [...tags].map((tag) => ({
      params: { tag }
    }));

    routePaths.push({ params: { tag: 'index' } });

    return routePaths;
  }
};

旧版

当有文章设置了分类标签,主题会根据 outDir (默认为根目录)自动生成 category.md (现在需要手动创建)

旧版的配置就非常简单了,只需要一个文件,在 outDir 对应的目录(默认为根目录)新建 category.md,复制以下内容。

旧版分类组件名为 CategoryClassic,分类与标签会在这个页面一起展示。

md
---
title: 分类
layout: page
---

<CategoryClassic />

除此之外,还需要在 themeConfig 中配置 classicCategory: true,将博客各处的跳转链接也修改为 query 风格的。

归档

归档页面同样需要手动创建,在 outDir 对应的目录(默认为根目录)新建 archives.md,并填入以下内容

md
---
title: 归档
layout: page
---

<Archives />

导航栏

添加分类页 / 标签页 / 归档页后,建议同时将其添加导航栏中

ts
// .vitepress/config.ts
export default defineConfigWithTheme<ThemeConfig>({
  themeConfig: {
    nav: [
      { text: '分类', link: '/category' },
      { text: '标签', link: '/tags' },
      { text: '归档', link: '/archives' }
    ]
  }
}

插槽

组件提供了 doc-afterdoc-before 插槽,可以在页面顶部和底部插入自定义组件

markdown
---
title: 归档
layout: page
---

<Category>
  <template #doc-after>
    <MyComponents />
  </template>
</Category>


<script lang="ts" setup>
import MyComponents from '.vitepress/theme/components/MyComponents.vue';
</script>
关注微信公众号