构建组件文档站
使用 VitePress 为 Vue 组件库创建专业的文档站点。
项目结构
text
my-ui/
├── docs/ # 文档目录
│ ├── .vitepress/
│ │ └── config.mts
│ ├── components/ # 组件文档
│ │ ├── button.md
│ │ └── input.md
│ └── index.md
├── src/ # 组件源码
│ ├── components/
│ │ ├── Button.vue
│ │ └── Input.vue
│ └── index.ts
└── package.json步骤 1:配置 VitePress
ts
// docs/.vitepress/config.mts
import { defineConfig } from 'vitepress'
import { resolve } from 'path'
export default defineConfig({
title: 'My UI',
description: 'Vue 组件库',
vite: {
resolve: {
alias: {
'@': resolve(__dirname, '../src')
}
}
},
themeConfig: {
logo: '/logo.svg',
nav: [
{ text: '首页', link: '/' },
{ text: '组件', link: '/components/button' },
{ text: '指南', link: '/guide/' }
],
sidebar: {
'/components/': [
{
text: '基础组件',
items: [
{ text: 'Button 按钮', link: '/components/button' },
{ text: 'Input 输入框', link: '/components/input' }
]
},
{
text: '表单组件',
items: [
{ text: 'Form 表单', link: '/components/form' }
]
}
]
}
}
})步骤 2:创建演示组件
方式一:直接引入组件
vue
<!-- docs/.vitepress/components/DemoBlock.vue -->
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{
title?: string
description?: string
}>()
const showCode = ref(false)
</script>
<template>
<div class="demo-block">
<div class="demo-preview">
<slot name="demo" />
</div>
<div class="demo-meta">
<div v-if="title" class="demo-title">{{ title }}</div>
<div v-if="description" class="demo-desc">{{ description }}</div>
</div>
<div class="demo-actions">
<button @click="showCode = !showCode">
{{ showCode ? '隐藏代码' : '显示代码' }}
</button>
</div>
<div v-show="showCode" class="demo-code">
<slot name="code" />
</div>
</div>
</template>
<style scoped>
.demo-block {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
margin: 1rem 0;
overflow: hidden;
}
.demo-preview {
padding: 1.5rem;
background: var(--vp-c-bg);
}
.demo-meta {
padding: 0 1.5rem;
border-top: 1px solid var(--vp-c-divider);
}
.demo-title {
font-weight: 600;
padding: 0.75rem 0 0.25rem;
}
.demo-desc {
color: var(--vp-c-text-2);
font-size: 0.875rem;
padding-bottom: 0.75rem;
}
.demo-actions {
border-top: 1px solid var(--vp-c-divider);
text-align: center;
}
.demo-actions button {
padding: 0.5rem 1rem;
background: none;
border: none;
cursor: pointer;
color: var(--vp-c-text-2);
font-size: 0.875rem;
}
.demo-actions button:hover {
color: var(--vp-c-brand-1);
}
.demo-code {
border-top: 1px solid var(--vp-c-divider);
}
</style>方式二:使用插件
安装 vitepress-theme-demoblock:
bash
npm install vitepress-theme-demoblock -Dts
// .vitepress/config.mts
import demoblock from 'vitepress-theme-demoblock'
export default defineConfig({
markdown: {
config: (md) => {
md.use(demoblock)
}
}
})步骤 3:编写组件文档
markdown
<!-- docs/components/button.md -->
---
title: Button 按钮
---
# Button 按钮
常用的操作按钮。
## 基础用法
使用 `type` 属性来定义按钮的样式。
<script setup>
import { Button } from '@/components'
</script>
<div class="demo">
<Button>默认按钮</Button>
<Button type="primary">主要按钮</Button>
<Button type="success">成功按钮</Button>
<Button type="warning">警告按钮</Button>
<Button type="danger">危险按钮</Button>
</div>
\`\`\`vue
<template>
<Button>默认按钮</Button>
<Button type="primary">主要按钮</Button>
<Button type="success">成功按钮</Button>
<Button type="warning">警告按钮</Button>
<Button type="danger">危险按钮</Button>
</template>
<script setup>
import { Button } from 'my-ui'
</script>
\`\`\`
## 禁用状态
使用 `disabled` 属性来控制按钮是否可用。
<div class="demo">
<Button disabled>禁用按钮</Button>
<Button type="primary" disabled>禁用按钮</Button>
</div>
\`\`\`vue
<Button disabled>禁用按钮</Button>
<Button type="primary" disabled>禁用按钮</Button>
\`\`\`
## API
### Props
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|------|------|------|--------|--------|
| type | 按钮类型 | string | primary / success / warning / danger | — |
| size | 尺寸 | string | large / small | — |
| disabled | 是否禁用 | boolean | — | false |
| loading | 是否加载中 | boolean | — | false |
### Events
| 事件名 | 说明 | 参数 |
|--------|------|------|
| click | 点击按钮时触发 | event |
### Slots
| 插槽名 | 说明 |
|--------|------|
| default | 按钮内容 |
| icon | 图标插槽 |
<style>
.demo {
padding: 1.5rem;
margin: 1rem 0;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
}
</style>步骤 4:注册全局组件
ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { Button, Input, Form } from '../../src/components'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// 注册组件
app.component('Button', Button)
app.component('Input', Input)
app.component('Form', Form)
}
}步骤 5:自动生成 API 文档
ts
// scripts/gen-component-docs.ts
import { parse } from 'vue-docgen-api'
import fs from 'fs'
import path from 'path'
async function generateDocs(componentPath: string, outputPath: string) {
const component = await parse(componentPath)
let markdown = `# ${component.displayName || 'Component'}\n\n`
if (component.description) {
markdown += `${component.description}\n\n`
}
// Props
if (component.props?.length) {
markdown += '## Props\n\n'
markdown += '| 参数 | 说明 | 类型 | 默认值 |\n'
markdown += '|------|------|------|--------|\n'
for (const prop of component.props) {
markdown += `| ${prop.name} | ${prop.description || '-'} | ${prop.type?.name || '-'} | ${prop.defaultValue?.value || '-'} |\n`
}
markdown += '\n'
}
// Events
if (component.events?.length) {
markdown += '## Events\n\n'
markdown += '| 事件名 | 说明 | 参数 |\n'
markdown += '|--------|------|------|\n'
for (const event of component.events) {
markdown += `| ${event.name} | ${event.description || '-'} | - |\n`
}
markdown += '\n'
}
// Slots
if (component.slots?.length) {
markdown += '## Slots\n\n'
markdown += '| 插槽名 | 说明 |\n'
markdown += '|--------|------|\n'
for (const slot of component.slots) {
markdown += `| ${slot.name} | ${slot.description || '-'} |\n`
}
}
fs.writeFileSync(outputPath, markdown)
}
// 使用
generateDocs('src/components/Button.vue', 'docs/components/button-api.md')学习检查清单
- [ ] 配置了组件库文档结构
- [ ] 创建了演示组件
- [ ] 编写了组件文档
- [ ] 注册了全局组件
- [ ] 生成了 API 文档