切换模式
Vitepress 获取所有文章列表
获取目录数据
createContentLoader,当构建一个内容为主的站点时,我们经常需要创建一个“归档”或“索引”页面:一个我们可以列出内容中的所有可用条目的页面,例如博客文章或 API 页面。我们可以直接使用数据加载 API 实现这一点,但由于这会经常使用,VitePress 还提供了一个 createContentLoader 辅助函数来简化这个过程:
js
// .vitepress\common\posts.data.ts
import { createContentLoader } from 'vitepress'
interface Post {
title: string
url: string
excerpt: string | undefined
}
declare const data: Post[]
export { data }
export default createContentLoader('posts/*.md', {
transform(raw): Post[] {
return raw.map(({ url, frontmatter }) => ({
title: frontmatter.title,
url,
excerpt: frontmatter.excerpt
}))
}
})在主题目录创建上面文件,读取posts/*.md的文件。
分页组件
PostList.vue组件放在与posts.data.ts相同位置,每10条做分页,以id倒序排列。
vue
<!-- .vitepress\theme\components\layout\PostList.vue -->
<script setup lang="ts">
import { computed, ref } from 'vue'
import { data as posts } from '../../../common/posts.data'
// 当前页数
const currentPage = ref(1)
// 每页文章数
const postsPerPage = 10
// 排序文章,按照倒序排列
const sortedPosts = computed(() => {
return [...posts].sort((a, b) => {
const idA = parseInt(a.url.replace('.html', ''))
const idB = parseInt(b.url.replace('.html', ''))
return idB - idA // 按照 ID 倒序排列
})
})
// 计算当前页的文章
const paginatedPosts = computed(() => {
const start = (currentPage.value - 1) * postsPerPage
const end = currentPage.value * postsPerPage
return sortedPosts.value.slice(start, end)
})
// 总页数
const totalPages = computed(() => {
return Math.ceil(sortedPosts.value.length / postsPerPage)
})
// 切换到下一页
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++
}
}
// 切换到上一页
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--
}
}
</script>
<template>
<h1>学习笔记</h1>
<div class="xxy">
<ul>
<li v-for="{ title, url, excerpt } of paginatedPosts">
<a :href="url">{{ title }}</a>
<span>by {{ excerpt }}</span>
</li>
</ul>
</div>
<!-- 分页控制按钮 -->
<div class="space-x-4">
<button @click="prevPage" :disabled="currentPage === 1">上一页</button>
<span>当前第 {{ currentPage }} 页 共 {{ totalPages }} 页</span>
<button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
</div>
</template>注册组件:
js
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import NotFound from './components/slot/NotFound.vue'
import PostList from './components/layout/PostList.vue'
import 'virtual:uno.css'
import './style.css'
import NoteDoc from './components/layout/NoteDoc.vue'
export default {
extends: DefaultTheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
'not-found': () => h(NotFound)
})
},
enhanceApp({ app, router, siteData }) {
app.component('PostList', PostList)
app.component('NoteDoc', NoteDoc)
}
} satisfies Theme获取文章列表
在文档目录创建 posts/1.md ,posts/2.md 等以数字 id 开头的 md 文档。
创建文章列表:note.md :
markdown
# 笔记收藏
<PostList />文章内容页
我这里沿用的是Vitepress 默认的文档页,新注册一个组件 NoteDoc
vue
<!-- .vitepress\theme\components\layout\NoteDoc.vue -->
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vitepress'
import { data as posts } from '../../../common/posts.data'
import VPDoc from 'vitepress/dist/client/theme-default/components/VPDoc.vue'
const route = useRoute()
function findCurrentIndex() {
return posts.findIndex((p) => p.url === route.path)
}
const nextPost = computed(() => posts[findCurrentIndex() - 1])
const prevPost = computed(() => posts[findCurrentIndex() + 1])
</script>
<template>
<VPDoc>
<template #doc-top><slot name="doc-top" /></template>
<template #doc-bottom><slot name="doc-bottom" /></template>
<template #doc-footer-before><slot name="doc-footer-before" /></template>
<template #doc-before><slot name="doc-before" /></template>
<template #doc-after><slot name="doc-after" /></template>
<template #aside-top><slot name="aside-top" /></template>
<template #aside-outline-before><slot name="aside-outline-before" /></template>
<template #aside-outline-after><slot name="aside-outline-after" /></template>
<template #aside-ads-before><slot name="aside-ads-before" /></template>
<template #aside-ads-after><slot name="aside-ads-after" /></template>
<template #aside-bottom><slot name="aside-bottom" /></template>
</VPDoc>
<div class="container mx-auto">
<div class="content flex justify-between">
<div v-if="nextPost" class="py-8">
<div class="text-xs tracking-wide uppercase">上一篇</div>
<div class="link">
<a :href="nextPost.url">{{ nextPost.title }}</a>
</div>
</div>
<div v-if="prevPost" class="py-8">
<div class="text-xs tracking-wide uppercase">下一篇</div>
<div class="link">
<a :href="prevPost.url">{{ prevPost.title }}</a>
</div>
</div>
</div>
</div>
</template>默认展示方式同文档页一样,自己单独加上了上一篇和下一篇 。
markdown
---
layout: NoteDoc
title: Windows环境下安装Nvm配置NodeJS环境
excerpt: 使用NVM搭建NodeJS环境的安装步骤
---
# 笔记标题
笔记内容需要展示为笔记的在头部添加 layout: NoteDoc。
本站笔记就是这样做的 收藏笔记