知识库站点
本教程介绍如何使用 VitePress 搭建一个个人知识库/笔记站点。
项目结构
knowledge-base/
├── docs/
│ ├── .vitepress/
│ │ ├── config.mts
│ │ └── data/
│ │ └── notes.data.ts
│ ├── notes/
│ │ ├── frontend/
│ │ │ ├── vue/
│ │ │ └── react/
│ │ ├── backend/
│ │ └── devops/
│ ├── daily/
│ │ └── 2024/
│ └── index.md
└── package.json配置文件
ts
// docs/.vitepress/config.mts
import { defineConfig } from 'vitepress'
export default defineConfig({
title: '我的知识库',
description: '个人知识管理与笔记系统',
themeConfig: {
logo: '/logo.svg',
nav: [
{ text: '首页', link: '/' },
{
text: '笔记',
items: [
{ text: '前端开发', link: '/notes/frontend/' },
{ text: '后端开发', link: '/notes/backend/' },
{ text: '运维部署', link: '/notes/devops/' }
]
},
{ text: '日常记录', link: '/daily/2024/' },
{ text: '标签', link: '/tags/' }
],
sidebar: {
'/notes/frontend/': [
{
text: '前端开发',
items: [
{ text: '概述', link: '/notes/frontend/' },
{
text: 'Vue.js',
collapsed: false,
items: [
{ text: '基础概念', link: '/notes/frontend/vue/basics' },
{ text: '组合式 API', link: '/notes/frontend/vue/composition' }
]
},
{
text: 'React',
collapsed: true,
items: [
{ text: '基础概念', link: '/notes/frontend/react/basics' }
]
}
]
}
],
'/notes/backend/': [
{
text: '后端开发',
items: [
{ text: '概述', link: '/notes/backend/' },
{ text: 'Node.js', link: '/notes/backend/nodejs' },
{ text: '数据库', link: '/notes/backend/database' }
]
}
],
'/daily/': [
{
text: '日常记录',
items: [
{ text: '2024', link: '/daily/2024/' }
]
}
]
},
search: {
provider: 'local',
options: {
detailedView: true
}
},
outline: {
label: '目录',
level: [2, 3]
}
}
})笔记数据加载器
ts
// docs/.vitepress/data/notes.data.ts
import { createContentLoader } from 'vitepress'
export interface Note {
title: string
url: string
date: string
tags: string[]
category: string
excerpt: string
}
export default createContentLoader('notes/**/*.md', {
excerpt: true,
transform(raw): Note[] {
return raw
.map(({ url, frontmatter, excerpt }) => ({
title: frontmatter.title || '无标题',
url,
date: frontmatter.date || '',
tags: frontmatter.tags || [],
category: frontmatter.category || '',
excerpt
}))
.sort((a, b) => +new Date(b.date) - +new Date(a.date))
}
})笔记模板
笔记 Frontmatter
yaml
---
title: Vue 组合式 API 详解
date: 2024-01-15
tags:
- Vue
- 前端
category: 前端开发
author: 张三
---笔记内容模板
markdown
---
title: 笔记标题
date: 2024-01-15
tags:
- 标签1
- 标签2
category: 分类
---
# 笔记标题
## 概述
简要描述笔记内容...
## 详细内容
### 要点一
详细说明...
### 要点二
详细说明...
## 代码示例
\`\`\`javascript
// 示例代码
\`\`\`
## 参考资料
- [参考链接1](url)
- [参考链接2](url)
## 相关笔记
- [[相关笔记1]]
- [[相关笔记2]]标签页面
创建 docs/tags.md:
markdown
---
title: 标签索引
---
<script setup>
import { data as notes } from '.vitepress/data/notes.data'
import { ref, computed } from 'vue'
const allTags = computed(() => {
const tagMap = new Map()
notes.forEach(note => {
note.tags.forEach(tag => {
if (!tagMap.has(tag)) {
tagMap.set(tag, [])
}
tagMap.get(tag).push(note)
})
})
return Array.from(tagMap.entries()).sort((a, b) => b[1].length - a[1].length)
})
const selectedTag = ref(null)
const filteredNotes = computed(() => {
if (!selectedTag.value) return []
return notes.filter(n => n.tags.includes(selectedTag.value))
})
</script>
<div class="tags-page">
<h1>标签索引</h1>
<div class="tags-cloud">
<button
v-for="[tag, noteList] in allTags"
:key="tag"
:class="['tag', { active: selectedTag === tag }]"
@click="selectedTag = tag"
>
{{ tag }} <span class="count">{{ noteList.length }}</span>
</button>
</div>
<div v-if="selectedTag" class="notes-list">
<h2>{{ selectedTag }} 相关笔记</h2>
<ul>
<li v-for="note in filteredNotes" :key="note.url">
<a :href="note.url">{{ note.title }}</a>
<span class="date">{{ note.date }}</span>
</li>
</ul>
</div>
</div>
<style>
.tags-page {
padding: 20px 0;
}
.tags-cloud {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 32px;
}
.tag {
padding: 8px 16px;
background: var(--vp-c-default-soft);
border: none;
border-radius: 20px;
cursor: pointer;
transition: all 0.2s;
}
.tag:hover,
.tag.active {
background: var(--vp-c-brand-1);
color: white;
}
.count {
opacity: 0.7;
margin-left: 4px;
}
.notes-list ul {
list-style: none;
padding: 0;
}
.notes-list li {
padding: 12px 0;
border-bottom: 1px solid var(--vp-c-divider);
display: flex;
justify-content: space-between;
}
.date {
color: var(--vp-c-text-2);
font-size: 14px;
}
</style>搜索功能增强
ts
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
detailedView: true,
miniSearch: {
searchOptions: {
fuzzy: 0.2,
prefix: true,
boost: { title: 4, text: 2, titles: 1 }
}
}
}
}
}
})双向链接
创建简单的双向链接支持:
vue
<!-- docs/.vitepress/theme/components/WikiLink.vue -->
<script setup>
import { computed } from 'vue'
const props = defineProps({
target: String
})
const link = computed(() => {
// 将 [[笔记名]] 转换为链接
return `/notes/${props.target.toLowerCase().replace(/\s+/g, '-')}`
})
</script>
<template>
<a :href="link" class="wiki-link">{{ target }}</a>
</template>
<style>
.wiki-link {
color: var(--vp-c-brand-1);
background: var(--vp-c-brand-soft);
padding: 2px 6px;
border-radius: 4px;
}
</style>最近更新组件
vue
<script setup>
import { data as notes } from '.vitepress/data/notes.data'
const recentNotes = notes.slice(0, 10)
</script>
<div class="recent-notes">
<h3>最近更新</h3>
<ul>
<li v-for="note in recentNotes" :key="note.url">
<a :href="note.url">{{ note.title }}</a>
</li>
</ul>
</div>最佳实践
| 实践 | 说明 |
|---|---|
| 分类清晰 | 使用目录结构组织内容 |
| 标签管理 | 为笔记添加多个标签便于查找 |
| 定期整理 | 定期回顾和更新笔记内容 |
| 搜索优化 | 利用搜索功能快速定位 |
| 链接关联 | 使用双向链接连接相关知识 |
下一步
查看 站点统计 为站点添加访问统计。
🎯 进阶挑战
完成基础教程后,尝试以下挑战来提升你的技能:
挑战 1:Markdown 双向链接 ⭐⭐⭐⭐
目标:实现类似 Obsidian 的 [[笔记名]] 双向链接语法。
提示:
- 创建自定义 Markdown 插件
- 解析
[[...]]语法 - 自动生成反向链接列表
参考思路:
ts
// 自定义 Markdown 插件
const wikiLinkPlugin = (md) => {
md.inline.ruler.before('link', 'wiki_link', (state, silent) => {
// 解析 [[笔记名]] 语法
const match = /^\[\[([^\]]+)\]\]/.exec(state.src.slice(state.pos))
if (match) {
// 创建链接 token
// ...
}
})
}挑战 2:知识图谱可视化 ⭐⭐⭐⭐⭐
目标:使用力导向图展示笔记之间的关系网络。
提示:
- 使用 D3.js 或 ECharts
- 分析笔记间的链接关系
- 实现交互式图谱
挑战 3:笔记全屏演示模式 ⭐⭐⭐
目标:将笔记转换为类似 PPT 的演示模式。
提示:
- 按
##标题分割内容 - 创建幻灯片切换动画
- 添加键盘导航
挑战 4:笔记导入导出 ⭐⭐⭐
目标:支持从其他笔记工具导入,以及导出为多种格式。
提示:
- 支持 Markdown 文件批量导入
- 支持从 Notion/Obsidian 导入
- 导出为 PDF/HTML
挑战 5:笔记版本历史 ⭐⭐⭐⭐
目标:记录笔记的修改历史,支持版本对比和回滚。
提示:
- 使用 Git 历史记录
- 或自定义版本存储
- 实现差异对比展示
挑战 6:智能笔记推荐 ⭐⭐⭐⭐⭐
目标:基于内容相似度推荐相关笔记。
提示:
- 提取笔记关键词
- 计算相似度分数
- 在页面底部展示推荐