Skip to content

组件结构

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

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                     # 公共组件
  ├─ ArticlePage                # 文章页组件
  ├─ Avatar                     # 头像组件
  ├─ Breadcrumb                 # 面包屑组件
  ├─ FocusTrap                  # 聚焦组件
  ├─ icon                       # 图标组件
  ├─ ImageViewer                # 图片查看器组件
  ├─ InputSlide                 # 滑块组件
  ├─ Message                    # 消息提示组件
  ├─ HomeCard                   # 分页卡片组件
  ├─ Pagination                 # 分页组件
  ├─ Popover                    # 弹窗组件
  ├─ Segmented                  # 分段控制器组件
  ├─ TitleTag                   # 标题标签组件
  ├─ TransitionCollapse         # 折叠动画组件
  ├─ VerifyCode                 # 随机验证码组件
  ├─ VpContainer                # VitePress 容器组件

  ├─ theme                      # 主题组件
  ├─ ArchivesPage               # 归档页组件
  ├─ ArticleAnalyze             # 文章页分析组件
  ├─ ArticleAppreciation        # 文章页赞赏组件
  ├─ ArticleBreadcrumb          # 文章页面包屑组件
  ├─ ArticleHeadingHighlight    # 文章页标题高亮组件
  ├─ ArticleImagePreview        # 图片预览组件
  ├─ ArticleInfo                # 文章信息组件
  ├─ ArticleOverviewPage        # 清单页组件
  ├─ ArticlePageStyle           # 文章页样式组件
  ├─ ArticleShare               # 文章页分页组件
  ├─ ArticleTitle               # 文章标题组件
  ├─ ArticleUpdate              # 文章最近更新栏组件
  ├─ BodyBgImage                # Body 背景图片组件
  ├─ CataloguePage              # 目录页组件
  ├─ CodeBlockToggle            # 代码块加强组件
  ├─ CommentArtalk              # Artalk 评论区组件
  ├─ CommentGiscus              # Giscus 评论区组件
  ├─ CommentTwikoo              # Twikoo 评论区组件
  ├─ CommentWaline              # Waline 评论区组件
  ├─ ConfigProvider             # Teek 入口文件
  ├─ DemoCode                   # Demo 容器组件
  ├─ FooterGroup                # 底部信息组组件
  ├─ FooterInfo                 # 底部信息组件
  ├─ Home                       # 首页组件
  ├─ HomeBanner                 # 首页 Banner 组件
  ├─ HomeCardList               # 首页卡片栏组件
  ├─ HomeCategoryCard           # 首页分类卡片组件
  ├─ HomeDocAnalysisCard        # 首页文章分析卡片组件
  ├─ HomeFriendLinkCard         # 首页友情链接卡片组件
  ├─ HomeFullscreenWallpaper    # 壁纸模式组件
  ├─ HomeMyCard                 # 首页我的卡片组件
  ├─ HomePostList               # 首页文章列表组件
  ├─ HomeTagCard                # 首页标签卡片组件
  ├─ HomeTopArticleCard         # 首页置顶文章卡片组件
  ├─ Layout                     # 布局组件(入口组件)
  ├─ LoginPage                  # 登录页
  ├─ Notice                     # 公告组件
  ├─ RightBottomButton          # 右下角按钮组组件
  ├─ RiskLinkPage               # 风险链接提示页
  ├─ ThemeEnhance               # 主题增强面板组件

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

配置项获取

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

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

  1. .vitepress/config.mts 全局配置
  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 种配置方式如下(index.md 文章页.mdfrontmatter 方式):

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"
---
最近更新