在 VitePress 中自动生成 Markdown 页面列表

在使用 VitePress 构建文档站点时,我们常常希望自动列出某个目录下的 Markdown 文件(例如教程、FAQ、练习题等)。
本文将介绍如何构建一个通用 Vue 组件,实现自动读取指定目录下以数字命名的 Markdown 文件,提取其标题,并生成排序后的链接列表。

🧱 推荐目录结构

docs/
├── components/
│   └── AutoList.vue       ← 自动读取组件
├── faqs/
│   ├── 1.md
│   ├── 2.md
├── en/faqs/
│   ├── 1.md
│   └── 2.md
├── faq.md                 ← 中文列表页
├── en/faq.md             ← 英文列表页
├── .vitepress/
│   └── theme/
│       └── index.ts       ← 注册 AutoList 组件

📦 组件代码(AutoList.vue)

<script setup>
import { ref } from "vue";

const props = defineProps({
  basePath: {
    type: String,
    required: true,
  },
});

const files = import.meta.glob("/**/*.md", { eager: true });
const list = ref([]);

for (const path in files) {
  if (path.startsWith(props.basePath)) {
    const match = path.match(/\/(\d+)\.md$/);
    if (match) {
      const id = match[1];
      const title = files[path].__pageData?.title || `文档 ${id}`;
      list.value.push({
        id,
        title,
        link: path.replace(/^\/(.*)\.md$/, "/$1.html"),
      });
    }
  }
}

list.value.sort((a, b) => Number(a.id) - Number(b.id));
</script>

<template>
  <div class="auto-list">
    <ul>
      <li v-for="item in list" :key="item.id">
        <a :href="item.link">{{ item.title }}</a>
      </li>
    </ul>
  </div>
</template>

🔧 注册组件(.vitepress/theme/index.ts)

要在 Markdown 页面中使用该组件,需要将其注册为全局组件:

// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import AutoList from '../../components/AutoList.vue'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('AutoList', AutoList)
  }
}

📝 在 Markdown 页面中使用

现在你可以在任意页面中直接使用 <AutoList /> 组件:

<AutoList basePath="/faqs/" />

若你在英文页面使用,则:

<AutoList basePath="/en/faqs/" />

📌 注意事项

  • Markdown 文件名需为纯数字,如 1.md2.md
  • 每个文件应有 title 字段,位于 frontmatter 中
  • 组件默认按 ID 从小到大排序
  • 路径拼接时会自动加上 .html 后缀

✅ 应用场景

  • FAQ 问题列表
  • 教程章节导航
  • 练习题列表
  • 多语言文章目录

借助这个组件,你可以让内容维护人员专注于撰写内容,而无需手动维护索引导航。

发表回复