Skip to content

组件结构

一个项目的功能组件虽然有很多,但是入口组件只有一个,如果您不知道这些功能组件都在哪里执行,不妨从入口组件开始解读,一步一步往下延伸,最终把项目功能吃透。

Teek 在首页、文章页、空白页、全局都写了组件来实现功能,但是这些组件并不是分开引入,而是统一在 src/layout/index.vue 里引入,并派发到 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 { tkTheme = true } = theme.value;
</script>

<template>
  <template v-if="tkTheme">
    <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 $slots" :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
├─ layout                        # 布局组件(入口组件)
├─ configProvider.ts            # 入口文件

├─ components
  ├─ ArchivesPage               # 归档页组件
  ├─ ArticleAnalyze             # 文章页分析组件
  ├─ ArticleBreadcrumb          # 文章页面包屑组件
  ├─ ArticleImagePreview        # 图片预览组件
  ├─ ArticleInfo                # 文章信息组件
  ├─ ArticlePageStyle           # 文章页样式组件
  ├─ base                       # 基础样式组件
  ├─ BodyBgImage                # Body 背景图片组件
  ├─ CataloguePage              # 目录页组件
  ├─ CodeBlockToggle            # 代码块加强组件
  ├─ CommentArtalk              # Artalk 评论区组件
  ├─ CommentGiscus              # Giscus 评论区组件
  ├─ CommentTwikoo              # Twikoo 评论区组件
  ├─ CommentWaline              # Waline 评论区组件
  ├─ Footer                     # 底部组件
  ├─ Home                       # 首页组件
  ├─ HomeBanner                 # 首页 Banner 组件
  ├─ HomeCard                   # 首页卡片组件
  ├─ HomeCategoryCard           # 首页分类卡片组件
  ├─ HomeDocAnalysisCard        # 首页文章分析卡片组件
  ├─ HomeFriendLinkCard         # 首页友情链接卡片组件
  ├─ HomeFullscreenWallpaper    # 壁纸模式组件
  ├─ HomeInfo                   # 首页信息组件
  ├─ HomeMyCard                 # 首页我的卡片组件
  ├─ HomePostList               # 首页文章列表组件
  ├─ HomeTagCard                # 首页标签卡片组件
  ├─ HomeTopArticleCard         # 首页置顶文章卡片组件
  ├─ Icon                       # 图标组件
  ├─ ImageViewer                # 图片查看器组件
  ├─ Notice                     # 公告组件
  ├─ Pagination                 # 分页组件
  └─ RightBottomButton          # 右下角按钮组组件

Vitepress 从 src/index.ts(入口文件)解析 Layout 函数,该函数返回 src/layout.index.vue 组件(入口组件),该入口组件将 Teek 的各个功能组件派发到 Vitepress 不同的插槽,最终形成现在的 Teek 主题。

配置项获取

在开发功能组件的时候,Teek 往往不会在组件内部固定功能,而是由用户通过配置项来开关功能,也叫插拔式设计。

在 Vitepress 中,配置项往往有 2 种方式配置:

  1. .vitepress/config.ts 全局配置
  2. 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 种配置方式如下:

ts
// .vitepress/config.ts
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"
---