Skip to content

插槽布局

插槽

Teek 提供了很多的插槽,能够被用来在页面的特定位置注入内容,下面这个例子展示了将一个组件注入到首页右侧卡片栏底部:

ts
// .vitepress/theme/index.ts
import Teek from "vitepress-theme-teek";
import MyLayout from "./MyLayout.vue";
import "vitepress-theme-teek/index.css";

export default {
  extends: Teek,
  // 使用注入插槽的包装组件覆盖 Layout
  Layout: MyLayout,
};
vue
<!-- .vitepress/theme/MyLayout.vue -->
<script setup>
import Teek from "vitepress-theme-teek";

const { Layout } = Teek;
</script>

<template>
  <Layout>
    <template #teek-home-info-after>自定义卡片栏</template>
  </Layout>
</template>

也可以使用 h 渲染函数。

ts
// .vitepress/theme/index.ts
import Teek from "vitepress-theme-teek";
import "vitepress-theme-teek/index.css";
import { h } from "vue";
import MyComponent from "./components/MyComponent.vue";

export default {
  extends: Teek,
  Layout() {
    return h(Teek.Layout, null, {
      "teek-home-info-after": () => h(MyComponent),
    });
  },
};

Teek 主题的全部插槽如下:

首页插槽

layout: 'home' 在 frontmatter 中被启用时:

  • teek-home-before:等于 VitePress 的 home-hero-before 插槽
  • teek-home-after

当首页为文档风格时启用:

  • teek-home-features-before v1.4.1
  • teek-home-features-after v1.4.1:等于 VitePress 的 home-features-after 插槽
  • teek-home-banner-before
  • teek-home-banner-after
  • teek-home-banner-content-before
  • teek-home-banner-content-after
  • teek-home-banner-feature-before
  • teek-home-banner-feature-after
  • teek-home-banner-name v1.4.0:覆盖 Banner 的文字,利用该插槽可以使用组件美化标题。可以接收 1 个参数,即配置项传过来的 name

如下是 Teek 当前实现的效果示例:

vue
<script setup lang="ts">
import Teek from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-home-banner-name="{ name }">
      <!-- 该 class 会激活 Teek 的内置样式 -->
      <h1 class="tk-banner-content__title" aria-label="首页横幅标题">
        {{ name }}
      </h1>
    </template>
  </Teek.Layout>
</template>

文章列表插槽

  • teek-home-post-before
  • teek-home-post-after
  • teek-home-post-list v1.2.0

Teek 默认实现了列表风格和卡片风格的文章列表,如果您需要定制自己的文章列表风格,可以通过 teek-home-post-list 插槽来覆盖 Teek 自带的文章列表,该插槽返回了当前的文章列表数量 currentPosts

vue
<script setup lang="ts">
import Teek from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-home-post-list="{ currentPosts, transitionName }">
      <TransitionGroup tag="ul" :name="transitionName">
        <li v-for="post in currentPosts" :key="post.url">
          <span>文章地址:{{ post.url }}</span>
          <span>文章 frontmatter 数据:{{ post.frontmatter }}</span>
          <span>文章摘要:{{ post.excerpt }}</span>
          <span>文章作者:{{ post.author }}</span>
          <span>文章 frontmatter.title:{{ post.title }}</span>
          <span>文章 frontmatter.date:{{ post.date }}</span>
          <span>文章前 300 个文字:{{ post.capture }}</span>
        </li>
      </TransitionGroup>
    </template>
  </Teek.Layout>
</template>

v-bind 返回的 transitionName 为 post 配置项的 transitionName,具体可以查看 Teek 的列表风格和卡片风格的代码实现。

卡片栏插槽

  • teek-home-card-before
  • teek-home-card v1.3.1
  • teek-home-card-after
  • teek-home-card-my-before
  • teek-home-card-my v1.3.1
  • teek-home-card-my-after
  • teek-home-card-top-article-before
  • teek-home-card-top-article v1.3.1
  • teek-home-card-top-article-after
  • teek-home-card-category-before
  • teek-home-card-category v1.3.1
  • teek-home-card-category-after
  • teek-home-card-tag-before
  • teek-home-card-tag v1.3.1
  • teek-home-card-tag-after
  • teek-home-card-friend-link-before
  • teek-home-card-friend-link v1.3.1
  • teek-home-card-friend-link-after
  • teek-home-card-doc-analysis-before
  • teek-home-card-doc-analysis v1.3.1
  • teek-home-card-doc-analysis-after

移动端插槽:

  • teek-home-card-my-screen-before v1.3.1
  • teek-home-card-my-screen v1.3.1
  • teek-home-card-my-screen-after v1.3.1

不带 -before-after 的插槽是直接覆盖卡片本身。

底部插槽

  • teek-footer-info-before
  • teek-footer-info-after:等于 VitePress 的 layout-bottom 插槽
  • teek-footer-info v1.4.5
  • teek-footer-group-before v1.5.0
  • teek-footer-group-after v1.5.0

文章页插槽

layout: 'doc' 在 frontmatter 中被启用时:

  • teek-article-analyze-before:等于 VitePress 的 doc-before 插槽
  • teek-article-analyze-after
  • teek-article-share-before
  • teek-article-share-after:等于 VitePress 的 aside-outline-before 插槽
  • teek-doc-after-appreciation-before:等于 VitePress 的 doc-after 插槽
  • teek-doc-after-appreciation-after:等于 Teek 的 teek-comment-before 插槽
  • teek-comment-before
  • teek-comment-after
  • teek-aside-bottom-appreciation-before:等于 VitePress 的 aside-bottom 插槽
  • teek-aside-bottom-appreciation-after
  • teek-doc-update-before v1.2.0
  • teek-doc-update-after v1.2.0
  • teek-article-bottom-tip-before v1.4.6
  • teek-article-bottom-tip-after v1.4.6
  • teek-article-banner-before v1.5.0:等于 VitePress 的 layout-top 插槽
  • teek-article-banner-after v1.5.0
  • teek-article-banner-info-top v1.5.0
  • teek-article-banner-info-bottom v1.5.0

功能页插槽

layout: 'page' 在 frontmatter 中被启用时:

  • teek-page-top-before:等于 VitePress 的 page-top 插槽
  • teek-page-top-after

归档页插槽

  • teek-archives-top-before
  • teek-archives-top-after

目录页插槽

  • teek-catalogue-top-before
  • teek-catalogue-top-after

登录页插槽

  • teek-login-page v1.3.0:覆盖 Teek 的登录页,适用于自己实现一个登录页

风险链接提示页

  • teek-risk-link-page v1.3.0:覆盖 Teek 的风险链接提示页,适用于自己实现一个风险链接提示页

全局插槽

右下角按钮组插槽

  • teek-right-bottom-before
  • teek-right-bottom-after
  • teek-back-top v1.4.0:覆盖回到顶部组件,可以接收 4 个参数:
    1. show:是否显示,当处于顶部时为 false,往下滚动后为 true,可用于控制组件的显示
    2. progress:当前滚动条的进度
    3. icon:内置的默认图标
    4. scrollToTop:回到顶部方法

如:

vue
<script setup lang="ts">
import Teek, { TkIcon } from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-back-top="{ show, progress, scrollToTop }">
      <!-- 如下是 Teek 当前实现的部分内容,这些 class 会激活 Teek 的内置样式 -->
      <div
        v-show="show"
        title="回到顶部"
        @click="scrollToTop"
        class="tk-right-bottom-button__button back-top"
        :style="{ '--tk-progress': progress, cursor: 'pointer' }"
        role="button"
        aria-label="回到顶部"
        :aria-valuenow="progress"
        aria-valuemin="0"
        aria-valuemax="100"
      >
        <span class="content">{{ progress }}</span>
      </div>
    </template>
  </Teek.Layout>
</template>
  • teek-to-comment v1.4.0:覆盖滚动到评论区组件,可以接收 3 个参数:
    1. show:是否显示,当处于评论区域时为 false,离开评论区域为 true,可用于控制组件的显示
    2. icon:内置的默认图标
    3. scrollToComment:滚动到评论区方法

如下是 Teek 当前实现的效果示例:

vue
<script setup lang="ts">
import Teek, { TkIcon } from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-to-comment="{ show, icon, scrollToComment }">
      <!-- 如下是 Teek 当前实现的部分内容,这些 class 会激活 Teek 的内置样式 -->
      <div
        title="滚动到评论区"
        class="tk-right-bottom-button__button"
        @click="scrollToComment"
        role="button"
        aria-label="滚动到评论区"
      >
        <TkIcon :icon="icon" aria-hidden="true" />
      </div>
    </template>
  </Teek.Layout>
</template>

提示

只有当页面存在评论区时,该功能/插槽才会生效。

其他插槽

  • teek-sidebar-trigger v1.4.0:覆盖侧边栏展开/折叠触发器组件,可以接收 2 个参数:
    1. active:点击触发器后为 true300s 后为 false,目的是可以添加一个 classstyle 来实现部分功能(过渡动画等)
    2. icon:icon:内置的默认图标
    3. toggleSideBar:点击触发器事件

如下是 Teek 当前实现的效果示例:

vue
<script setup lang="ts">
import Teek, { TkIcon } from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-sidebar-trigger="{ active, icon, toggleSideBar }">
      <!-- 如下是 Teek 当前实现的部分内容,这些 class 会激活 Teek 的内置样式 -->
      <div :class="{ active: active }" class="tk-sidebar-trigger is-active" @click="toggleSideBar">
        <div class="tk-right-bottom-button__button">
          <TkIcon :icon="icon" />
        </div>
      </div>
    </template>
  </Teek.Layout>
</template>
  • teek-loading v1.4.0:切换页面(路由)时加载 Loading 动画,切换结束关闭 Loading 动画插槽,可以接收 1 个参数:
    1. loading:开始切换页面(路由)时为 true,切换结束为 false

如下是 Teek 当前实现的效果示例:

vue
<script setup lang="ts">
import Teek, { TkIcon } from "vitepress-theme-teek";
</script>

<template>
  <Teek.Layout>
    <template #teek-loading="{ loading }">
      <!-- 如下是 Teek 当前实现的部分内容,这些 class 会激活 Teek 的内置样式 -->
      <div class="tk-route-loading">
        <div v-show="loading" class="tk-route-loading__mask">
          <div class="tk-route-loading__loader">
            <div class="tk-route-loading__spinner" />
            <p>Teek 拼命加载中 ...</p>
          </div>
        </div>
      </div>
    </template>
  </Teek.Layout>
</template>

主题增强插槽

  • teek-theme-enhance-top
  • teek-theme-enhance-bottom

VitePress 插槽

其实官方也提供了不少 插槽,可以按需使用。

例如 not-found 插槽可以帮我们自定义 404 页面。

配置过程:

新建 404.vue

新建 docs\.vitepress\theme\components\404.vue 文件,代码如下:

vue
<script setup lang="ts">
import { withBase, useRouter } from "vitepress";

const router = useRouter();

const ns = "error-page";
</script>

<template>
  <div :class="[ns, 'flx-center']">
    <img :src="withBase('/404.png')" :class="`${ns}__img`" alt="404" />
    <div :class="[`${ns}__detail`, 'flx-column']">
      <h2>404</h2>
      <h4>抱歉,您访问的页面不存在~🤷‍♂️🤷‍♀️</h4>
      <button @click="router.go('/')">返回首页</button>
    </div>
  </div>
</template>

<style scoped lang="scss">
$namespace: error-page;

.#{$namespace} {
  width: 100%;
  height: calc(100vh - var(--vp-nav-height));
  gap: 120px;

  &__detail {
    h2 {
      font-size: 60px;
      color: var(--vp-c-text-1);
      line-height: 1;
    }
    h4 {
      margin: 10px 0 20px 0;
      font-size: 19px;
      font-weight: normal;
      color: var(--vp-c-text-2);
    }

    button {
      color: #ffffff;
      background-color: #395ae3;
      box-shadow: 0 2px 0 rgba(5, 145, 255, 0.1);
      font-size: 14px;
      width: 100px;
      height: 32px;
      padding: 4px 15px;
      border-radius: 6px;
      outline: none;
      position: relative;
      display: inline-block;
      font-weight: 400;
      white-space: nowrap;
      text-align: center;
      background-image: none;
      border: 1px solid transparent;
      cursor: pointer;
      transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
      user-select: none;
      touch-action: manipulation;
      line-height: 1.5714285714285714;

      &:hover {
        background-color: #5a79f4;
      }
    }
  }

  @media (max-width: 768px) {
    flex-direction: column;
    gap: 60px;
    transform: translateY(-10%);
    &__detail {
      align-items: center;
    }
  }
}
</style>

新建 TeekLayoutProvider.vue

新建 docs\.vitepress\theme\components\TeekLayoutProvider.vue,在里面引用 404.vue

代码如下:

vue

<script setup lang="ts" name="TeekLayoutProvider">
import Teek from "vitepress-theme-teek";
import ContributeChart from "./ContributeChart.vue";
import NotFound from "./404.vue";

</script>

<template>
  <Teek.Layout>
    <template #not-found>
      <NotFound />
    </template>
  </Teek.Layout>
</template>

引用 TeekLayoutProvider

docs\.vitepress\theme\index.ts 引用 TeekLayoutProvider.vue

ts
import TeekLayoutProvider from "./components/TeekLayoutProvider.vue";

export default {
  extends: Teek,
  Layout: TeekLayoutProvider
}

说明:

  1. 404.vue 文件可以按需修改,网上有很多的模板参考(例如 404s63 HTML 404 Templates
  2. TeekLayoutProvider.vue 文件的作用是统一定义插槽。假如定义了很多页面,可以在这里统一引入
  3. 然后在 index.ts 引入 TeekLayoutProvider.vue 文件即可
最近更新