Skip to content
0

组件结构

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

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 种方式配置:

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