Skip to content
当前页导航

使用自定义主题

主题解析

您可以通过创建.vitepress/theme/index.js.vitepress/theme/index.ts文件("主题入口文件")来启用自定义主题:

.
├─ docs                # project root
│  ├─ .vitepress
│  │  ├─ theme
│  │  │  └─ index.js   # theme entry
│  │  └─ config.js     # config file
│  └─ index.md
└─ package.json

当 VitePress 检测到主题入口文件存在时,将始终使用自定义主题而不是默认主题。但是,您可以扩展默认主题 在其之上执行高级自定义。

主题界面

VitePress 自定义主题定义为具有以下接口的对象:

ts
interface Theme {
  /**
   * Root layout component for every page
   * @required
   */
  Layout: Component
  /**
   * Enhance Vue app instance
   * @optional
   */
  enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
  /**
   * Extend another theme, calling its `enhanceApp` before ours
   * @optional
   */
  extends?: Theme
}

interface EnhanceAppContext {
  app: App // Vue app instance
  router: Router // VitePress router instance
  siteData: Ref<SiteData> // Site-level metadata
}

主题入口文件应将主题导出为其默认导出:

js
// .vitepress/theme/index.js

// You can directly import Vue files in the theme entry
// VitePress is pre-configured with @vitejs/plugin-vue.
import Layout from './Layout.vue'

export default {
  Layout,
  enhanceApp({ app, router, siteData }) {
    // ...
  }
}

默认导出是自定义主题的唯一契约,并且只需要layout属性。因此从技术上讲,VitePress 主题可以像单个 Vue 组件一样简单。

在布局组件内,它的工作方式就像普通的 Vite + Vue 3 应用程序一样。请注意,主题还需要SSR 兼容

构建布局

最基本的布局组件需要包含一个 <Content /> 组件:

vue
<!-- .vitepress/theme/Layout.vue -->
<template>
  <h1>Custom Layout!</h1>

  <!-- this is where markdown content will be rendered -->
  <Content />
</template>

上面的布局只是将每个页面的 markdown 呈现为 HTML。我们可以添加的第一个改进是处理 404 错误:

vue
<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。我们可以利用它来允许最终用户控制每个页面的布局。例如,用户可以指示页面应使用特殊的首页布局:

md
---
layout: home
---

我们可以调整我们的主题来处理这个问题:

vue
<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>

当然,您可以将布局拆分为更多组件:

vue
<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 包分发,请按照下列步骤操作:

  1. 将主题对象导出为包条目中的默认导出。

  2. 如果适用,将主题配置类型定义导出为themeConfig

  3. 如果您的主题需要调整 VitePress 配置,请将该配置导出到包子路径下(例如 my-theme/config),以便用户可以扩展它。

  4. 记录主题配置选项(通过配置文件和 frontmatter)。

  5. 提供有关如何使用主题的清晰说明(见下文)。

使用自定义主题

要使用外部主题,请从自定义主题条目导入并重新导出它:

js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'

export default Theme

如果主题需要扩展:

js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'

export default {
  extends: Theme,
  enhanceApp(ctx) {
    // ...
  }
}

如果主题需要特殊的 VitePress 配置,您还需要在自己的配置中扩展它:

ts
// .vitepress/theme/config.ts
import baseConfig from 'awesome-vitepress-theme/config'

export default {
  // extend theme base config (if needed)
  extends: baseConfig
}

最后,如果主题为其主题配置提供类型:

ts
// .vitepress/theme/config.ts
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: {
    // Type is `ThemeConfig`
  }
})

本文档由全栈行动派(qzxdp.cn)翻译并整理