主题 API
VitePress 主题是一个包含组件和样式的集合,本节介绍主题开发相关的 API。
主题入口文件
主题入口文件位于 .vitepress/theme/index.ts。
接口定义
ts
interface Theme {
// 扩展默认主题
extends?: Theme
// 布局组件
Layout?: Component
// 404 组件
NotFound?: Component
// 应用增强函数
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
// setup 函数
setup?: () => void
}扩展默认主题
基础扩展
ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
export default {
extends: DefaultTheme
}添加自定义样式
ts
import DefaultTheme from 'vitepress/theme'
import './custom.css'
export default {
extends: DefaultTheme
}注册全局组件
ts
import DefaultTheme from 'vitepress/theme'
import MyComponent from './components/MyComponent.vue'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('MyComponent', MyComponent)
}
}安装 Vue 插件
ts
import DefaultTheme from 'vitepress/theme'
import { createPinia } from 'pinia'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.use(createPinia())
}
}自定义主题
完全自定义主题需要提供 Layout 组件。
基础结构
ts
// .vitepress/theme/index.ts
import Layout from './Layout.vue'
export default {
Layout,
NotFound: () => import('./NotFound.vue'),
enhanceApp({ app }) {
// 注册全局组件和插件
}
}Layout 组件
vue
<!-- .vitepress/theme/Layout.vue -->
<script setup lang="ts">
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>
<template>
<div class="theme">
<header>导航栏</header>
<main>
<Content />
</main>
<footer>页脚</footer>
</div>
</template>布局插槽
默认主题提供了一系列插槽用于扩展布局。
Layout 插槽
vue
<!-- .vitepress/theme/index.ts -->
import DefaultTheme from 'vitepress/theme'
import MyLayout from './MyLayout.vue'
export default {
extends: DefaultTheme,
Layout: MyLayout
}vue
<!-- .vitepress/theme/MyLayout.vue -->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>
<template>
<Layout>
<!-- 导航栏前 -->
<template #nav-bar-title-before>
<span class="logo-icon">🚀</span>
</template>
<!-- 导航栏后 -->
<template #nav-bar-content-after>
<div class="custom-nav">自定义内容</div>
</template>
<!-- 侧边栏前 -->
<template #sidebar-nav-before>
<div class="sidebar-header">导航</div>
</template>
<!-- 文档前 -->
<template #doc-before>
<div class="doc-header">文档头</div>
</template>
<!-- 文档后 -->
<template #doc-after>
<div class="doc-footer">文档脚</div>
</template>
<!-- 页脚前 -->
<template #doc-footer-before>
<div class="custom-footer">自定义页脚</div>
</template>
</Layout>
</template>可用插槽列表
| 插槽名称 | 说明 |
|---|---|
layout-top | 布局顶部 |
layout-bottom | 布局底部 |
nav-bar-title-before | 导航标题前 |
nav-bar-title-after | 导航标题后 |
nav-bar-content-before | 导航内容前 |
nav-bar-content-after | 导航内容后 |
nav-screen-content-before | 移动端导航前 |
nav-screen-content-after | 移动端导航后 |
sidebar-nav-before | 侧边栏导航前 |
sidebar-nav-after | 侧边栏导航后 |
doc-before | 文档内容前 |
doc-after | 文档内容后 |
doc-footer-before | 页脚前 |
aside-top | 大纲顶部 |
aside-bottom | 大纲底部 |
aside-outline-before | 大纲前 |
aside-outline-after | 大纲后 |
aside-ads-before | 广告前 |
aside-ads-after | 广告后 |
enhanceApp
应用增强函数,用于注册全局组件、插件等。
参数
ts
interface EnhanceAppContext {
app: App // Vue 应用实例
router: Router // VitePress 路由
siteData: Ref<SiteData> // 站点数据
}注册全局组件
ts
export default {
enhanceApp({ app }) {
// 单个注册
app.component('MyButton', () => import('./components/MyButton.vue'))
// 批量注册
const components = import.meta.glob('./components/*.vue')
for (const [path, component] of Object.entries(components)) {
const name = path.match(/\/([^/]+)\.vue$/)[1]
app.component(name, component)
}
}
}添加全局指令
ts
export default {
enhanceApp({ app }) {
app.directive('focus', {
mounted(el) {
el.focus()
}
})
}
}提供全局数据
ts
export default {
enhanceApp({ app }) {
app.provide('globalConfig', {
api: 'https://api.example.com'
})
}
}useData
获取页面数据的组合式函数。
ts
import { useData } from 'vitepress'
const {
page, // 当前页面数据
frontmatter, // frontmatter 数据
theme, // 主题配置
site, // 站点数据
lang, // 当前语言
title, // 页面标题
description // 页面描述
} = useData()useRoute
获取当前路由信息。
ts
import { useRoute } from 'vitepress'
const route = useRoute()
console.log(route.path) // 当前路径
console.log(route.data) // 页面数据
console.log(route.component) // 页面组件useRouter
访问路由器实例。
ts
import { useRouter } from 'vitepress'
const router = useRouter()
// 导航
router.go('/guide/installation')
// 返回
router.go(-1)
// 监听路由变化
router.onAfterRouteChanged = (to) => {
console.log('导航到:', to)
}Content 组件
渲染 Markdown 内容的组件。
vue
<script setup>
import { Content } from 'vitepress'
</script>
<template>
<Content />
</template>Props
vue
<Content class="custom-content" />完整主题示例
ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import type { Theme } from 'vitepress'
import { h } from 'vue'
import MyComponent from './components/MyComponent.vue'
import './custom.css'
export default {
extends: DefaultTheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
'doc-after': () => h(MyComponent)
})
},
enhanceApp({ app, router }) {
// 注册组件
app.component('MyComponent', MyComponent)
// 路由守卫
router.onBeforeRouteChange = (to) => {
console.log('即将导航到:', to)
}
}
} satisfies Theme参考链接
- 主题配置 - 主题配置选项
- 运行时 API - 运行时 API
- VitePress 官方主题 API 文档