数据加载
VitePress 提供了多种方式来加载和处理数据。
数据加载器
创建数据加载器
在 docs/.vitepress/ 目录下创建数据文件:
ts
// docs/.vitepress/data/posts.data.ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
transform(raw): Post[] {
return raw
.map(({ url, frontmatter }) => ({
title: frontmatter.title,
url,
date: frontmatter.date,
excerpt: frontmatter.excerpt
}))
.sort((a, b) => +new Date(b.date) - +new Date(a.date))
}
})
interface Post {
title: string
url: string
date: string
excerpt: string
}使用数据
vue
<!-- docs/posts/index.md -->
<script setup>
import { data as posts } from '.vitepress/data/posts.data'
const recentPosts = posts.slice(0, 5)
</script>
# 最新文章
<ul>
<li v-for="post in recentPosts" :key="post.url">
<a :href="post.url">{{ post.title }}</a>
<span>{{ post.date }}</span>
</li>
</ul>createContentLoader API
基础用法
ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md')配置选项
ts
export default createContentLoader('posts/*.md', {
// 包含 src 和 excerpt
includeSrc: true,
// 渲染 excerpt 为 HTML
render: true,
// excerpt 分隔符
excerpt: '<!-- more -->',
// 转换函数
transform(raw) {
return raw.map(post => ({
...post,
// 自定义处理
}))
}
})返回数据结构
ts
interface ContentData {
url: string // 页面 URL
frontmatter: object // Frontmatter 数据
excerpt?: string // 摘要
src?: string // 原始内容
html?: string // 渲染后的 HTML
}静态数据文件
JSON 数据
json
// docs/data/authors.json
[
{ "name": "张三", "avatar": "/avatars/zhangsan.png" },
{ "name": "李四", "avatar": "/avatars/lisi.png" }
]在组件中使用:
vue
<script setup>
import authors from '../data/authors.json'
</script>
<ul>
<li v-for="author in authors" :key="author.name">
<img :src="author.avatar" :alt="author.name" />
{{ author.name }}
</li>
</ul>TypeScript 数据
ts
// docs/data/links.ts
export interface Link {
title: string
url: string
icon?: string
}
export const links: Link[] = [
{ title: 'GitHub', url: 'https://github.com', icon: 'github' },
{ title: 'Twitter', url: 'https://twitter.com', icon: 'twitter' }
]使用:
vue
<script setup lang="ts">
import { links } from '../data/links'
</script>
<a v-for="link in links" :key="link.url" :href="link.url">
{{ link.title }}
</a>运行时 API
useData
获取站点和页面数据:
ts
import { useData } from 'vitepress'
const {
site, // 站点级数据
page, // 当前页面数据
frontmatter,
themeConfig,
lang,
title,
description,
isDark
} = useData()useRoute
获取当前路由信息:
ts
import { useRoute } from 'vitepress'
const route = useRoute()
// route.path - 当前路径
// route.component - 当前组件useRouter
访问路由器:
ts
import { useRouter } from 'vitepress'
const router = useRouter()
function navigate() {
router.go('/guide/')
}构建时数据获取
从 API 获取数据
ts
// docs/.vitepress/data/github.data.ts
export default {
async load() {
const res = await fetch('https://api.github.com/repos/vuejs/vitepress')
return res.json()
}
}从文件系统读取
ts
// docs/.vitepress/data/posts.data.ts
import { readFileSync, readdirSync } from 'fs'
import { join } from 'path'
export default {
load() {
const dir = join(__dirname, '../../posts')
const files = readdirSync(dir)
return files
.filter(f => f.endsWith('.md'))
.map(f => ({
filename: f,
content: readFileSync(join(dir, f), 'utf-8')
}))
}
}博客示例
文章数据
ts
// docs/.vitepress/data/posts.data.ts
import { createContentLoader } from 'vitepress'
export default createContentLoader('blog/*.md', {
transform(raw) {
return raw
.map(({ url, frontmatter, excerpt }) => ({
title: frontmatter.title,
url,
date: formatDate(frontmatter.date),
author: frontmatter.author,
tags: frontmatter.tags || [],
excerpt
}))
.sort((a, b) => +new Date(b.date) - +new Date(a.date))
}
})
function formatDate(date: string) {
return new Date(date).toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}博客首页
markdown
---
title: 博客
---
<script setup>
import { data as posts } from '.vitepress/data/posts.data'
</script>
# 博客文章
<div v-for="post in posts" :key="post.url" class="post-card">
<h2><a :href="post.url">{{ post.title }}</a></h2>
<p class="meta">{{ post.date }} · {{ post.author }}</p>
<p>{{ post.excerpt }}</p>
<div class="tags">
<span v-for="tag in post.tags" :key="tag" class="tag">{{ tag }}</span>
</div>
</div>下一步
学习 多语言支持 来构建国际化站点。