Skip to content

构建时加载数据,生成列表

我们可以在构建时加载,比如用于生成一个目录的列表。

参考文档见:https://vitepress.dev/guide/data-loading

生成 blog 目录

1. 编写加载函数 blog.data.ts

ts
// file: ./.vitepress/theme/blog.data.ts
import fs from 'node:fs'

export default {
  watch: ['../../blog/*.md'],
  load(watchedFiles) {
    // watchedFiles will be an array of absolute paths of the matched files.
    // generate an array of blog post metadata that can be used to render
    // a list in the theme layout
    return watchedFiles.map((file) => {
      return fs.readFileSync(file, 'utf-8')
    })
  }
}

2. 在 blog.md 中使用

为避免 blog.md 放在 ./blog/目录中也被载入,或需要剔除,我们将之放在 . 目录。

md
<script setup>
import { data as posts } from './.vitepress/theme/blog.data.ts'

console.log(posts)
</script>

<h1>All Blog Posts</h1>
<ul>
  <li v-for="post of posts">
    {{ post }}
  </li>
</ul>

效果如下图所示:

使用 createContentLoader

我们还可以更便捷地使用 createContentLoader 来加载 .md 等数据。

例如,我们在 ./blog/ 目录有如下文件:

blog
├── 20240401-vitepress-intro.md
├── 20240403-vitepress-howto.md
└── 20240410-vitepress-tutorial.md

其中每个文件有 frontmatter 如下:

md
---
title: 'vitepress tutorial'
author: 'VP'
---

1. 编写 loader

修改 blog.data.ts 为:

ts
// file: ./.vitepress/theme/blog.data.ts
import { createContentLoader } from 'vitepress'

export default createContentLoader('blog/*.md', /* options */)

2. 编写一个目录组件

vue
// file: ./.vitepress/theme/BlogHome.ts
<script setup>
import { data as posts } from './blog.data.ts'
</script>

<template>
  <h1>All Blog Posts</h1>
  <ul>
    <li v-for="post of posts">
      <a :href="post.url">{{ post.frontmatter.title }}</a>
      <span>by {{ post.frontmatter.author }}</span>
    </li>
  </ul>
</template>

3.在 index.ts中注册组件

ts
import BlogHome  from './BlogHome.vue'

export default {
  extends: DefaultTheme,
  enhanceApp({ app, router, siteData }) {
    app.component("BlogHome", BlogHome );
  }
} satisfies Theme

4. 在页面中使用

我们在首页(index.md)增加:

md
<div class='mt-20'>
  <BlogHome />
</div>

你可以不全局注册组件(不做之前的第三步),而仅在需要时导入,如下:

md

<div class='mt-20'>
  <BlogHome />
</div>

<script setup lang="ts">
import BlogHome from './.vitepress/theme/BlogHome.vue'
</script>

效果如下:

添加 "type":"module"

要能成功使用如下代码,需要对 package.json 进行调整,增加:

json
{
  "type": "module",
  "scripts": {
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs"
  },
}

添加 "type": "module" 是为了让 Node.js 把 .js 文件当作 ESM 来处理。

否则会遇到错误 ERROR: [plugin: externalize-deps] "vitepress" resolved to an ESM file. ESM file cannot be loaded by require. See https://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only for more details.

相关文档与讨论:文档讨论

Alang.AI - Make Great AI Applications