Skip to content

布局插槽

布局插槽允许你在默认主题的特定位置插入自定义内容,实现灵活的页面定制。

版本说明

  • 本文档基于 VitePress v1.0.0+ 编写
  • 所有布局插槽在 v0.22.0+ 版本中可用
  • 部分插槽可能在后续版本中新增

使用插槽

创建自定义布局组件

vue
<!-- docs/.vitepress/theme/Layout.vue -->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>

<template>
  <Layout>
    <!-- 在这里使用插槽 -->
  </Layout>
</template>

注册布局

ts
// docs/.vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import Layout from './Layout.vue'

export default {
  extends: DefaultTheme,
  Layout
}

可用插槽

页面级别插槽

插槽位置用途版本要求
layout-top页面最顶部全局通知、横幅v0.22.0+
layout-bottom页面最底部自定义脚本、统计v0.22.0+
vue
<template>
  <Layout>
    <template #layout-top>
      <div class="banner">
        🎉 VitePress 2.0 已发布!
      </div>
    </template>
    
    <template #layout-bottom>
      <div class="custom-footer">
        自定义页脚内容
      </div>
    </template>
  </Layout>
</template>

导航栏插槽

插槽位置版本要求
nav-bar-title-before标题 Logo 前v0.22.0+
nav-bar-title-after标题 Logo 后v0.22.0+
nav-bar-content-before导航链接前v0.22.0+
nav-bar-content-after导航链接后v0.22.0+
vue
<template>
  <Layout>
    <!-- Logo 前添加图标 -->
    <template #nav-bar-title-before>
      <span class="logo-icon">📚</span>
    </template>
    
    <!-- 导航右侧添加搜索以外的内容 -->
    <template #nav-bar-content-after>
      <a href="/changelog" class="changelog-link">
        更新日志
      </a>
    </template>
  </Layout>
</template>

移动端导航插槽

插槽位置版本要求
nav-screen-content-before移动端导航内容前v0.22.0+
nav-screen-content-after移动端导航内容后v0.22.0+
vue
<template>
  <Layout>
    <!-- 仅移动端显示 -->
    <template #nav-screen-content-after>
      <div class="mobile-menu-footer">
        <a href="/about">关于我们</a>
      </div>
    </template>
  </Layout>
</template>

侧边栏插槽

插槽位置版本要求
sidebar-nav-before侧边栏导航前v0.22.0+
sidebar-nav-after侧边栏导航后v0.22.0+
vue
<template>
  <Layout>
    <!-- 侧边栏顶部 -->
    <template #sidebar-nav-before>
      <div class="sidebar-header">
        <input type="text" placeholder="搜索..." />
      </div>
    </template>
    
    <!-- 侧边栏底部 -->
    <template #sidebar-nav-after>
      <div class="sidebar-footer">
        <a href="/feedback">反馈建议</a>
      </div>
    </template>
  </Layout>
</template>

文档内容插槽

插槽位置版本要求
doc-before文档内容前v0.22.0+
doc-after文档内容后v0.22.0+
doc-footer-before页脚导航前v0.22.0+
vue
<template>
  <Layout>
    <!-- 文档顶部添加面包屑 -->
    <template #doc-before>
      <nav class="breadcrumb">
        <a href="/">首页</a>
        <span>/</span>
        <span>当前页面</span>
      </nav>
    </template>
    
    <!-- 文档底部添加评论 -->
    <template #doc-after>
      <div class="comments">
        <!-- 评论组件 -->
      </div>
    </template>
  </Layout>
</template>

右侧栏插槽

插槽位置版本要求
aside-top右侧栏顶部v0.22.0+
aside-bottom右侧栏底部v0.22.0+
aside-outline-before大纲前v0.22.0+
aside-outline-after大纲后v0.22.0+
vue
<template>
  <Layout>
    <!-- 大纲上方 -->
    <template #aside-outline-before>
      <div class="page-info">
        阅读时间: 5 分钟
      </div>
    </template>
    
    <!-- 右侧栏底部 -->
    <template #aside-bottom>
      <div class="edit-page">
        <a :href="editLink">编辑此页</a>
      </div>
    </template>
  </Layout>
</template>

完整示例

vue
<!-- docs/.vitepress/theme/Layout.vue -->
<script setup>
import DefaultTheme from 'vitepress/theme'
import { useData } from 'vitepress'
import { computed } from 'vue'

const { Layout } = DefaultTheme
const { page, frontmatter } = useData()

const editLink = computed(() => {
  return `https://github.com/user/repo/edit/main/docs/${page.value.relativePath}`
})
</script>

<template>
  <Layout>
    <!-- 顶部横幅 -->
    <template #layout-top>
      <div v-if="frontmatter.banner" class="banner">
        {{ frontmatter.banner }}
      </div>
    </template>
    
    <!-- Logo 图标 -->
    <template #nav-bar-title-before>
      <img src="/logo.svg" alt="Logo" class="logo-icon" />
    </template>
    
    <!-- 侧边栏搜索 -->
    <template #sidebar-nav-before>
      <div class="sidebar-search">
        <input type="text" placeholder="搜索文档..." />
      </div>
    </template>
    
    <!-- 文档顶部信息 -->
    <template #doc-before>
      <div v-if="frontmatter.date" class="doc-meta">
        <span class="date">{{ frontmatter.date }}</span>
        <span v-if="frontmatter.author" class="author">
          作者: {{ frontmatter.author }}
        </span>
      </div>
    </template>
    
    <!-- 文档底部 -->
    <template #doc-after>
      <div class="doc-contribution">
        <h3>贡献者</h3>
        <p>感谢所有贡献者!</p>
      </div>
    </template>
    
    <!-- 右侧栏 -->
    <template #aside-outline-after>
      <div class="aside-info">
        <a :href="editLink">📝 编辑此页</a>
      </div>
    </template>
  </Layout>
</template>

<style scoped>
.banner {
  background: var(--vp-c-brand-soft);
  padding: 8px 24px;
  text-align: center;
  font-size: 14px;
}

.logo-icon {
  width: 24px;
  height: 24px;
  margin-right: 8px;
}

.sidebar-search {
  padding: 12px 16px;
}

.sidebar-search input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--vp-c-divider);
  border-radius: 6px;
  background: var(--vp-c-bg-soft);
}

.doc-meta {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
  font-size: 14px;
  color: var(--vp-c-text-2);
}

.doc-contribution {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--vp-c-divider);
}

.aside-info {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--vp-c-divider);
}

.aside-info a {
  display: block;
  padding: 8px 0;
  color: var(--vp-c-text-2);
}
</style>

下一步

接下来学习 组件使用 来创建交互式内容。

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献