写一个自定义页面
除了写会进入首页、归档和标签页的文章,还可以在知识库中创建独立页面,例如友链、关于、项目展示或工具页。
本主题为普通页面提供 layout: page。它会复用主题的页面信息区、正文卡片和个人资料侧栏,但不会显示文章日期、文章目录或评论。
先区分文章和页面
| 用途 | layout | 是否进入文章流 |
|---|---|---|
| 博文、笔记、教程 | doc | 是 |
| 友链、关于、项目、工具 | page | 否 |
因此,页面不要使用 layout: doc,否则它会被当作文章处理。
最小页面
以友链页面为例,在知识库根目录创建下面的结构:
FriendLink/
├── index.md
└── FriendLinkPage.vue其中 FriendLink/index.md 对应网站地址 /FriendLink/。目录中的 index.md 总是映射为该目录的首页;例如 Tools/status.md 对应 /Tools/status。
先写入口文件 FriendLink/index.md:
---
title: 友链
layout: page
---
<script setup lang="ts">
import FriendLinkPage from './FriendLinkPage.vue'
</script>
<FriendLinkPage />title 会由页面信息区展示,所以 Vue 组件通常不必再写一个重复的一级标题。
然后创建 FriendLink/FriendLinkPage.vue:
<template>
<section class="friend-link-page" aria-label="友情链接">
<p>这里放置页面的实际内容。</p>
</section>
</template>
<style scoped>
.friend-link-page {
min-width: 0;
}
</style>现在访问 /FriendLink/ 就能看到页面。主题已经提供正文卡片容器,组件内部通常使用普通的 section、列表或网格即可,不要再为整个页面套一层 a-card,避免产生嵌套卡片。
从配置读取数据
页面可以通过 VitePress 的 useData() 读取根目录 site_config.yml 中的主题配置。当前友链页就是这样读取 friendlink:
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'
interface FriendLink {
Name: string
Url: string
Avatar?: string
Desc?: string
}
interface PageTheme {
friendlink?: FriendLink[]
}
const { theme } = useData<PageTheme>()
const links = computed(() => theme.value.friendlink ?? [])
</script>对应的 site_config.yml 配置示例:
friendlink:
- Name: "示例博客"
Url: "https://example.com/"
Avatar: "/Avatar.png"
Desc: "一段简短的介绍"配置驱动的方式适合友链、项目列表、联系方式等经常更新而不想改 Vue 文件的内容。复杂的交互和展示逻辑则放在 Vue 组件中,保持配置只描述数据。
资源与浏览器 API
页面专属图片可以与组件放在同一目录,并通过相对路径引用;所有页面共用的图片、SVG 和字体资源建议放到根目录 public/ 中,再以 / 开头的路径引用:
public/
└── image/
└── project-cover.webp<img src="/image/project-cover.webp" alt="项目封面">普通 Vue 组件可以直接渲染。只有组件在初始化时直接访问 window、document、localStorage,或依赖仅支持浏览器的第三方库时,才需要使用 ClientOnly:
<script setup lang="ts">
import BrowserOnlyWidget from './BrowserOnlyWidget.vue'
</script>
<ClientOnly>
<BrowserOnlyWidget />
</ClientOnly>不要为普通组件一律加上 ClientOnly,否则会失去服务端渲染和首屏内容。
添加导航入口
页面文件创建后不会自动出现在导航中。可在根目录 site_config.yml 的 menuItems 中加入入口:
menuItems:
- key: more
label: 更多
icon: compass
children:
- key: friends
label: 友链
icon: users
link: /FriendLink/link 使用网站路径,而不是本地文件路径。图标可使用 Lucide 的 kebab-case 名称,例如 users、book-open;品牌图标也可以使用已有的 Font Awesome fa-* 类名或 iconUrl。
页面样式建议
- 将样式写在组件的
<style scoped>中,避免影响文章和其他页面。 - 页面框架已经处理了宽屏侧栏与移动端排版,组件只需要处理自己的内容布局。
- 列表和卡片使用
min-width: 0、文本省略和响应式网格,避免窄屏横向溢出。 - 外链使用
target="_blank" rel="noopener noreferrer"。 - 使用主题颜色变量,例如
var(--vp-c-text-1)、var(--vp-c-brand)和var(--vp-c-content-surface),以便自动适配深色模式。
常见问题
页面出现在首页文章列表中
检查 frontmatter。普通页面应使用:
layout: page访问地址不正确
检查目录和文件名。FriendLink/index.md 的地址是 /FriendLink/,不是 /FriendLink/index.md。
构建时报 window 或 document 未定义
将直接访问浏览器 API 的逻辑移到 onMounted(),或只为对应组件包裹 ClientOnly。
修改配置后页面没有变化
确认修改的是知识库根目录的 site_config.yml,字段名称与组件读取的字段一致;推送知识库后,部署工作流会重新构建网站。
完成后可参考本仓库的 FriendLink/ 目录:入口文件负责路由与布局,Vue 文件负责页面内容,site_config.yml 负责可编辑的数据和导航入口。