组件结构
一个项目的功能组件虽然有很多,但是入口组件只有一个,如果您不知道这些功能组件都在哪里执行,不妨从入口组件开始解读,一步一步往下延伸,最终把项目功能吃透。
Teek 在首页、文章页、空白页、全局都写了组件来实现功能,但是这些组件并不是分开引入,而是统一在 Layout 组件里引入,并派发到 VitePress 不同的插槽,如:
vue
<!-- src/layout/index.vue -->
<script setup lang="ts" name="TeekLayout">
import DefaultTheme from "vitepress/theme";
import { useData } from "vitepress";
import {
RightBottomButton,
Notice,
Home,
Footer,
ArticleAnalyze,
Comment,
ArchivesPage,
CataloguePage,
} from "../components";
const { Layout } = DefaultTheme;
const { theme } = useData();
const { teekTheme = true } = theme.value;
// 维护已使用的插槽,防止外界传来的插槽覆盖已使用的插槽
const usedSlots = [
"home-hero-before",
"nav-bar-content-after",
// 其他模板里已使用的插槽 ...
];
</script>
<template>
<template v-if="teekTheme">
<ClientOnly>
<!-- 全局组件 -->
<RightBottomButton />
<Notice />
</ClientOnly>
<Layout :class="ns.b()">
<template #home-hero-before>
<slot name="home-hero-before" />
<ClientOnly>
<!-- 自定义首页 -->
<Home />
</ClientOnly>
</template>
<template #layout-bottom>
<!-- 底部组件 -->
<Footer v-if="isHomePage()" />
<slot name="layout-bottom" />
</template>
<template #doc-before>
<slot name="doc-before" />
<!--文章页信息组件 -->
<ArticleAnalyze />
</template>
<template #doc-after>
<slot name="doc-after" />
<!-- 评论区组件 -->
<Comment />
</template>
<template #page-top>
<slot name="page-top" />
<ArchivesPage />
<CataloguePage />
</template>
<!-- 未使用的其他 VP 插槽 -->
<template
v-for="(_, name) in Object.keys($slots).filter(name => !usedSlots.includes(name))"
:key="name"
#[name]="slotData"
>
<slot :name="name" v-bind="slotData"></slot>
</template>
</Layout>
</template>
<template v-else>
<Layout>
<template v-for="(_, name) in $slots" :key="name" #[name]="slotData">
<slot :name="name" v-bind="slotData"></slot>
</template>
</Layout>
</template>
</template>目录结构
sh
src
│
├─ components
│ ├─ base # 基础样式组件
│ │
│ ├─ common # 公共组件
│ │ ├─ article-page # 文章页组件
│ │ ├─ avatar # 头像组件
│ │ ├─ breadcrumb # 面包屑组件
│ │ ├─ focus-trap # 聚焦组件
│ │ ├─ icon # 图标组件
│ │ ├─ image-viewer # 图片查看器组件
│ │ ├─ input-slide # 滑块组件
│ │ ├─ message # 消息提示组件
│ │ ├─ home-card # 分页卡片组件
│ │ ├─ pagination # 分页组件
│ │ ├─ popover # 弹窗组件
│ │ ├─ segmented # 分段控制器组件
│ │ ├─ title-tag # 标题标签组件
│ │ ├─ transition-collapse # 折叠动画组件
│ │ ├─ verify-code # 随机验证码组件
│ │ ├─ vp-container # VitePress 容器组件
│ │
│ ├─ theme # 主题组件
│ │ ├─ article-analyze # 文章页分析组件
│ │ ├─ article-appreciation # 文章页赞赏组件
│ │ ├─ article-banner # 文章页 Banner 组件
│ │ ├─ article-breadcrumb # 文章页面包屑组件
│ │ ├─ article-code-block # 代码块加强组件
│ │ ├─ article-heading-highlight # 文章页标题高亮组件
│ │ ├─ article-image-preview # 图片预览组件
│ │ ├─ article-info # 文章信息组件
│ │ ├─ article-page-style # 文章页样式组件
│ │ ├─ article-share # 文章页分页组件
│ │ ├─ article-title # 文章标题组件
│ │ ├─ article-update # 文章最近更新栏组件
│ │ ├─ body-bg-image # Body 背景图片组件
│ │ ├─ comment-artalk # Artalk 评论区组件
│ │ ├─ comment-giscus # Giscus 评论区组件
│ │ ├─ comment-twikoo # Twikoo 评论区组件
│ │ ├─ comment-waline # Waline 评论区组件
│ │ ├─ config-provider # Teek 入口文件
│ │ ├─ demo-code # Demo 容器组件
│ │ ├─ footer-group # 底部信息组组件
│ │ ├─ footer-info # 底部信息组件
│ │ ├─ home-banner # 首页 Banner 组件
│ │ ├─ home-card # 首页卡片栏组件
│ │ ├─ home-card-category # 首页分类卡片组件
│ │ ├─ home-card-doc-analysis # 首页文章分析卡片组件
│ │ ├─ home-card-friend-link # 首页友情链接卡片组件
│ │ ├─ home-card-my # 首页我的卡片组件
│ │ ├─ home-card-tag # 首页标签卡片组件
│ │ ├─ home-card-top-article # 首页置顶文章卡片组件
│ │ ├─ home-feature # 首页 banner 的 Feature 组件
│ │ ├─ home-fullscreen-wallpaper # 壁纸模式组件
│ │ ├─ home-main # 首页组件
│ │ ├─ home-post # 首页文章列表组件
│ │ ├─ layout # 布局组件(入口组件)
│ │ ├─ notice # 公告组件
│ │ ├─ page-archives # 归档页组件
│ │ ├─ page-article-overview # 清单页组件
│ │ ├─ page-catalogue # 目录页组件
│ │ ├─ page-login # 登录页
│ │ ├─ page-risk-link # 风险链接提示页
│ │ ├─ right-bottom-button # 右下角按钮组组件
│ │ ├─ route-loading # 路由切换加载动画组件
│ │ ├─ sidebar-trigger # 侧边栏折叠/展开组件
│ │ ├─ theme-enhance # 主题增强面板组件VitePress 从 src/index.ts(入口文件)解析 Layout 函数,该函数返回 src/layout.index.vue 组件(入口组件),该入口组件将 Teek 的各个功能组件派发到 VitePress 不同的插槽,最终形成现在的 Teek 主题。
配置项获取
在开发功能组件的时候,Teek 往往不会在组件内部固定功能,而是由用户通过配置项来开关功能。
在 VitePress 中,配置项往往有 2 种方式配置:
.vitepress/config.mts全局配置- Markdown 的
frontmatter局部配置
如果 2 种方式都配置,那么 Markdown 的 frontmatter 配置优先级更改,比如 Teek 的评论区功能,用户可以给每一个 Markdown 配置不同的评论区。
配置项获取的例子如:
vue
<script setup lang="ts">
import { computed } from "vue";
import { useData } from "vitepress";
const { theme, frontmatter } = useData();
const commentConfig = computed(() => ({
...theme.comment,
...frontmatter.value.comment,
...frontmatter.value.tk.comment, // 首页 index.md 配置项
}));
</script>
<template></template>这样编写方式既支持 2 种方式配置,也支持给配置项添加默认值。2 种配置方式如下(index.md 和 文章页.md 是 frontmatter 方式):
ts
// .vitepress/config.mts
import { defineTeekConfig } from "vitepress-theme-teek/config";
const teekConfig = defineTeekConfig({
comment: {
provider: "giscus",
options: {
repo: "your repo",
repoId: "your repoId",
category: "your category",
categoryId: "your categoryId",
}
};
});yaml
---
tk:
comment:
provider: "giscus"
options:
repo: "your repo"
repoId: "your repoId"
category: "your category"
categoryId: "your categoryId"
---yaml
---
comment:
provider: "giscus"
options:
repo: "your repo"
repoId: "your repoId"
category: "your category"
categoryId: "your categoryId"
---