自訂主題
解析主題
可以通過建立一个 .vitepress/theme/index.js 或 .vitepress/theme/index.ts 文件 (即“主題入口文件”) 来啟用自訂主題:
.
├─ docs # 项目根目录
│ ├─ .vitepress
│ │ ├─ theme
│ │ │ └─ index.js # 主題入口
│ │ └─ config.js # 配置文件
│ └─ index.md
└─ package.json当检測到存在主題入口文件时,VitePress 总會使用自訂主題而不是默认主題。但你可以扩展默认主題来在其基础上实现更高级的自訂。
主題介面
VitePress 自訂主題是一个对象,该对象具有如下介面:
interface Theme {
/**
* 每个頁面的根布局组件
* @required
*/
Layout: Component
/**
* 增强 Vue 应用实例
* @optional
*/
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
/**
* 扩展另一个主題,在我们的主題之前呼叫它的 `enhanceApp`
* @optional
*/
extends?: Theme
}
interface EnhanceAppContext {
app: App // Vue 应用实例
router: Router // VitePress 路由实例
siteData: Ref<SiteData> // 站點级元数据
}主題入口文件需要将主題作为默认导出来导出:
// 可以直接在主題入口导入 Vue 文件
// VitePress 已预先配置 @vitejs/plugin-vue
import Layout from './Layout.vue'
export default {
Layout,
enhanceApp({ app, router, siteData }) {
// ...
}
}默认导出是自訂主題的唯一方式,并且只有 Layout 属性是必须的。所以从技术上讲,一个 VitePress 主題可以是一个单独的 Vue 组件。
在组件内部,它的工作方式就像是一个普通的 Vite + Vue 3 应用。请注意,主題还需要保证 SSR 相容。
构建布局
最基本的布局组件需要包含一个 <Content /> 组件:
<template>
<h1>Custom Layout!</h1>
<!-- 此处将渲染 markdown 内容 -->
<Content />
</template>上面的布局只是将每个頁面的 markdown 渲染为 HTML。我们新增的第一个改进是處理 404 错误:
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<template>
<h1>Custom Layout!</h1>
<div v-if="page.isNotFound">
Custom 404 page!
</div>
<Content v-else />
</template>useData() 为我们提供了所有的執行階段数据,以便我们根据不同条件渲染不同的布局。我们可以访问的另一个数据是目前頁面的 frontmatter。通過利用这个数据,可以让用户单独控制每个頁面的布局。例如,用户可以指定一个頁面是否使用特殊的主页布局:
---
layout: home
---并且我们可以调整主題进行處理:
<script setup>
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>
<template>
<h1>Custom Layout!</h1>
<div v-if="page.isNotFound">
Custom 404 page!
</div>
<div v-if="frontmatter.layout === 'home'">
Custom home page!
</div>
<Content v-else />
</template>当然你可以将布局切分为不同的组件:
<script setup>
import { useData } from 'vitepress'
import NotFound from './NotFound.vue'
import Home from './Home.vue'
import Page from './Page.vue'
const { page, frontmatter } = useData()
</script>
<template>
<h1>Custom Layout!</h1>
<NotFound v-if="page.isNotFound" />
<Home v-if="frontmatter.layout === 'home'" />
<Page v-else /> <!-- <Page /> renders <Content /> -->
</template>请查看執行階段 API 參考获取主題组件中所有可用内容。此外,可以利用构建时数据加载来生成数据驱动布局——例如,一个列出目前项目中所有博客文章的頁面。
分發自訂主題
分發自訂主題最简单的方式是通過将其作为 GitHub 模版仓库。
如果你希望将主題作为 npm 包来分發,请按照下面的步驟操作:
在包入口将主題对象使用默认导出。
如果合适的话,将主題配置类型定义作为
ThemeConfig导出。如果主題需要调整 VitePress 配置,请在包的子路径下 (例如
my-theme/config) 下导出该配置,以便用户扩展。记录主題配置选项 (通過配置文件和 frontmatter)。
提供清晰的說明,告诉用户如何使用主題 (见下文)。
使用自訂主題
要使用外部主題,请导入它并重新导出:
import Theme from 'awesome-vitepress-theme'
export default Theme如果主題需要扩展:
import Theme from 'awesome-vitepress-theme'
export default {
extends: Theme,
enhanceApp(ctx) {
// ...
}
}如果主題需要特殊的 VitePress 配置,也需要在配置中扩展:
import baseConfig from 'awesome-vitepress-theme/config'
export default {
// 扩展主題的基本配置(如需要)
extends: baseConfig
}最後,如果主題为其主題配置提供了类型:
import baseConfig from 'awesome-vitepress-theme/config'
import { defineConfigWithTheme } from 'vitepress'
import type { ThemeConfig } from 'awesome-vitepress-theme'
export default defineConfigWithTheme<ThemeConfig>({
extends: baseConfig,
themeConfig: {
// 类型为 `ThemeConfig`
}
})