在使用 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.md
、2.md
等 - 每个文件应有
title
字段,位于 frontmatter 中 - 组件默认按 ID 从小到大排序
- 路径拼接时会自动加上
.html
后缀
✅ 应用场景
- FAQ 问题列表
- 教程章节导航
- 练习题列表
- 多语言文章目录
借助这个组件,你可以让内容维护人员专注于撰写内容,而无需手动维护索引导航。