侧边栏

优质
小牛编辑
117浏览
2023-12-01

创建侧边栏对于以下目的很有用:

  • 相关文档 分组
  • 为每篇文档 显示一个侧边栏
  • 提供带有 下一页/上一页(next/previous)按钮的 分页导航

要为你的 Docusaurus 网站添加侧边栏的话,需要:

  1. 创建一个导出(export) 侧边栏对象(sidebar object) 的文件。
  2. 将此对象直接或通过 @docusaurus/preset-classic 传递给 @docusaurus/plugin-docs 插件。
docusaurus.config.js
module.exports = {
  presets: [
    [
      '@docusaurus/preset-classic',
      {
        docs: {
          sidebarPath: require.resolve('./sidebars.js'),
}, }, ], ], };

默认侧边栏

默认情况下,Docusaurus 会根据 docs 的目录结构为你 自动生成一个侧边栏:

sidebars.js
module.exports = {
  mySidebar: [
    {
      type: 'autogenerated',
      dirName: '.', // 自动根据 `docs` 或 `versioned_docs/<version>` 目录的文件结构生成侧边栏分片
    },
  ],
};

你也可以自行定义侧边栏。

侧边栏对象(Sidebar object)

侧边栏是由 侧边栏条目(sidebar items) 组成的树形列表

type Sidebar =
  // 常规语法
  | SidebarItem[]
  // 简写语法
  | Record<
      string, // category label
      SidebarItem[] // category items
    >;

侧边栏定义文件可以包含 多个侧边栏对象(sidebar objects)

type SidebarsFile = Record<
  string, // sidebar id
  Sidebar
>;

示例:

sidebars.js
module.exports = {
  mySidebar: [
    {
      type: 'category',
      label: 'Getting Started',
      items: ['doc1'],
    },
    {
      type: 'category',
      label: 'Docusaurus',
      items: ['doc2', 'doc3'],
    },
  ],
};

在上述示例中,请注意以下几点:

  • 仅定义了一个侧边栏对象 mySidebar,其中包含 5 个 侧边栏条目(sidebar item)
  • Getting StartedDocusaurus 均属于侧边栏分类(category)
  • doc1doc2doc3 都是列于侧边栏中的文档
tip

使用 简写语法 可以更简洁地定义侧边栏,如下所示:

sidebars.js
module.exports = {
  mySidebar: {
    'Getting started': ['doc1'],
    Docusaurus: ['doc2', 'doc3'],
  },
};

使用多个侧边栏

你可以为 属于同一类一组 markdown 文档 创建一个侧边栏对象。

tip

Docusaurus 官网就是一个很好的使用多个侧边栏的实例:

示例:

sidebars.js
module.exports = {
  tutorialSidebar: {
    'Category A': ['doc1', 'doc2'],
  },
  apiSidebar: ['doc3', 'doc4'],
};
note

tutorialSidebarapiSidebar 分别是 定义不同侧边栏的 id,除此之外没有什么特殊意义。

当浏览文档时:

  • 浏览 doc1doc2 时: tutorialSidebar 侧边栏将被显示出来
  • 浏览 doc3doc4 时: apiSidebar 侧边栏将被显示出来

使用 上一页和下一页按钮 来显示 分页导航 时,其所链接的文档也是属于同一个侧边栏的。

了解侧边栏条目(sidebar items)

SidebarItem 是一个定义在侧边栏树形结构上的条目。

侧边栏条目(sidebar items)有多个不同的类型:

  • Doc 类型:链接到文档页面,并将此文档页面归属于当前侧边栏
  • Ref:链接到文档页面,不将此文档页面归属于当前侧边栏
  • Link:链接到任何站内或站外的页面
  • Category:为侧边栏条目创建层级结构
  • Autogenerated:自动生成一个侧边栏切片(slice)

Doc:链接到文档

使用 doc 类型来链接到某个文档页面,并将此页面归属于某个侧边栏:

type SidebarItemDoc =
  // 常规语法
  | {
      type: 'doc';
      id: string;
      label: string; // 用于在侧边栏上显示的文本标题或标签
    }
  // 简写语法
  | string; // 文档 id(docId)的简写形式

示例:

sidebars.js
module.exports = {
  mySidebar: [
    // 常规语法:
    {
type: 'doc', id: 'doc1', // 文档 id label: 'Getting started', // 显示在侧边栏上的标题或标签(label) }, // 简写语法: 'doc2', // 文档 id ], };

markdown 元数据(frontmatter)中定义的 sidebar_label 的优先级高于(也就是会覆盖) SidebarItemDoc 中所定义的 label

note

不要将同一份文档归属给多个侧边栏:如有需要,请使用 ref 代替。

Ref:链接到文档页面,并且不归属到当前侧边栏

使用 ref 类型用于链接到文档页面,并且不将文档页面归属到当前侧边栏。

type SidebarItemRef = {
  type: 'ref';
  id: string;
};

示例:

sidebars.js
module.exports = {
  mySidebar: [
    {
      type: 'ref',
      id: 'doc1', // 文档 id (字符串类型)。
    },
  ],
};

当浏览 doc1 时,Docusaurus 将不会显示 id 为 mySidebar 的侧边栏。

Link:链接到任意页面

使用 link 类型可以链接到任何非文档的页面(站内或站外的页面都可以)。

type SidebarItemLink = {
  type: 'link';
  label: string;
  href: string;
};

示例:

sidebars.js
module.exports = {
  myLinksSidebar: [
    // 站外链接
{ type: 'link', label: 'Facebook', // 为此链接设置的标题(label) href: 'https://facebook.com', // 站外链接(URL) }, // 站内链接 { type: 'link', label: 'Home', // 为此链接设置的标题(label) href: '/', // 站内路径 }, ], };

Category:创建层级结构

使用 category 类型来为侧边栏创建层级结构。

type SidebarItemCategory = {
  type: 'category';
  label: string; // 展示在侧边栏上的文本标题(label)
  items: SidebarItem[]; // 侧边栏条目(sidebar items)数组。
  // Category options:
  collapsed: boolean; // 设置此分类是默认折叠还是展开
};

示例:

sidebars.js
module.exports = {
  docs: [
    {
      type: 'category',
      label: 'Guides',
      collapsed: false,
      items: [
        'creating-pages',
        {
          type: 'category',
          label: 'Docs',
          items: ['introduction', 'sidebar', 'markdown-features', 'versioning'],
        },
      ],
    },
  ],
};
tip

当不需要为 Category 类型定义参数时可以使用 简写语法

sidebars.js
module.exports = {
  docs: {
    Guides: [
      'creating-pages',
      {
        Docs: ['introduction', 'sidebar', 'markdown-features', 'versioning'],
      },
    ],
  },
};

折叠或展开分类

对于具有大量内容的网站,我们支持将分类做展开或折叠,以便显示或隐藏其所包含的子级条目。默认情况下,分类是处于折叠状态的。如果你希望所有分类都是展开的状态,可以将 themeConfig.sidebarCollapsible 设置为 false

docusaurus.config.js
module.exports = {
  themeConfig: {
    sidebarCollapsible: false,
}, };

默认展开分类

对于可折叠或展开的分类,你可能希望对某些分类进行更细粒度的控制。如果想将某个分类始终展开,可以为此分类设置 collapsedfalse

sidebars.js
module.exports = {
  docs: {
    Guides: [
      'creating-pages',
      {
        type: 'category',
        label: 'Docs',
        collapsed: false,
        items: ['markdown-features', 'sidebar', 'versioning'],
      },
    ],
  },
};

Autogenerated:生成侧边栏

Docusaurus 能够根据 目录结构 自动创建侧边栏:每个文件夹都将被创建为一个侧边栏分类。

Docusaurus 会将一个 autogenerated 条目转换为一个 侧边栏切片(sidebar slice):也就是一组 doccategory 类型的条目组成的列表。

type SidebarItemAutogenerated = {
  type: 'autogenerated';
  dirName: string; // 此目录(相对于 docs 目录)用于生成侧边栏切片(sidebar slice)。
};

Docusaurus 可以根据你的 docs 目录的文件结构生成一个侧边栏:

sidebars.js
module.exports = {
  myAutogeneratedSidebar: [
    {
type: 'autogenerated', dirName: '.', // '.' 指的是当前的 docs 目录(也就是存放文档的根目录) }, ], };

你可以为侧边栏使用 多个 autogenerated 条目,并将它们于常规定义的侧边栏条目交叉使用:

sidebars.js
module.exports = {
  mySidebar: [
    'intro',
    {
      type: 'category',
      label: 'Tutorials',
      items: [
        'tutorial-intro',
        {
type: 'autogenerated', dirName: 'tutorials/easy', // 根据 docs/tutorials/easy 目录的文件结构自动生成侧边栏切片(sidebar slice) }, 'tutorial-medium', { type: 'autogenerated', dirName: 'tutorials/advanced', // 根据 docs/tutorials/hard 目录的文件结构自动生成侧边栏切片(sidebar slice) }, 'tutorial-end', ], }, { type: 'autogenerated', dirName: 'guides', // 根据 docs/guides 目录的文件结构自动生成侧边栏切片(sidebar slice) }, { type: 'category', label: 'Community', items: ['team', 'chat'], }, ], };

自动生成侧边栏元数据(metadatas)

默认情况下,将依据文件和目录的名称并按照 字母表顺序 自动生成侧边栏切片(sidebar slice)。

如果自动生成的侧边栏看上去不合心意,还可以为文档和分类手工定义元数据。

对于文档:请使用 frontmatter 来定义额外的元数据:

docs/tutorials/tutorial-easy.md
+ ---
+ sidebar_label: Easy
+ sidebar_position: 2
+ ---
# Easy Tutorial This is the easy tutorial!

对于分类:请将 _category_.json_category_.yml 文件直接放置于目录下:

docs/tutorials/_category_.json
{
  "label": "Tutorial",
  "position": 3
}
docs/tutorials/_category_.yml
label: 'Tutorial'
position: 2.5 # 也支持浮点数
collapsed: false # 默认展开此分类
info

position 参数 仅作用于侧边栏切片(sidebar slice):Docusaurus 并不会对侧边栏的其它条目做重新排序。

使用数字前缀

对自动生成的侧边栏做排序的简单方法是在文档和文件夹名称前添加数字前缀:

docs
├── 01-Intro.md
├── 02-Tutorial Easy
│   ├── 01-First Part.md
│   ├── 02-Second Part.md
│   └── 03-End.md
├── 03-Tutorial Hard
│   ├── 01-First Part.md
│   ├── 02-Second Part.md
│   ├── 03-Third Part.md
│   └── 04-End.md
└── 04-End.md

为了 便于采用 起见,Docusaurus 支持 多数字前缀模式

默认情况下,Docusaurus 将从自动生成的文档 id、标题、标签(label)和 URL 路径中 删除数字前缀

caution

推荐使用 frontmatter 来定义 额外的元数据(metadatas)

更新数字前缀是非常繁琐的,因为这可能需要 更新多个 markdown 文件中的链接

docs/02-Tutorial Easy/01-First Part.md
- Check the [Tutorial End](../04-End.md);
+ Check the [Tutorial End](../05-End.md);

自定义侧边栏生成器

你可以为 docs 插件(或预设)提供自定义的 sidebarItemsGenerator 侧边栏生成器函数:

docusaurus.config.js
module.exports = {
  plugins: [
    [
      '@docusaurus/plugin-content-docs',
      {
        sidebarItemsGenerator: async function ({
defaultSidebarItemsGenerator, numberPrefixParser, item, version, docs, }) { // 示例:返回一个预定义的侧边栏列表 return [ {type: 'doc', id: 'doc1'}, {type: 'doc', id: 'doc2'}, ]; }, }, ], ], };
tip

尽可能 重用或增强默认生成器 而不是从头编写一个全新的生成器。

根据具体使用场景来 添加、更新、过滤、重排序 侧边栏条目:

docusaurus.config.js
// 颠倒侧边栏条目的排序(包括嵌套的分类)
function reverseSidebarItems(items) { // Reverse items in categories const result = items.map((item) => { if (item.type === 'category') { return {...item, items: reverseSidebarItems(item.items)}; } return item; }); // 将当前级别的所有条目顺序颠倒 result.reverse(); return result;} module.exports = { plugins: [ [ '@docusaurus/plugin-content-docs', { sidebarItemsGenerator: async function ({ defaultSidebarItemsGenerator, ...args }) { const sidebarItems = await defaultSidebarItemsGenerator(args); return reverseSidebarItems(sidebarItems); }, }, ], ], };

可隐藏的侧边栏

通过 themeConfig.hideableSidebar 参数,你可以隐藏整个侧边栏,让你的用户可以更好地专注到内容上面。在中等尺寸的屏幕(例如平板设备)上阅读内容时,此功能特别有用。

docusaurus.config.js
module.exports = {
  themeConfig: {
    // highlight-starrt
    hideableSidebar: true,
  },
};

传递自定义参数

如果你重写或覆盖(swizzled)了侧边栏模板,并且希接收一些额外的参数,则可以为任意侧边栏条目定义一个可选的 customProps 对象:

{
  type: 'doc',
  id: 'doc1',
  customProps: {
    /* props */
  }
}

结构复杂的侧边栏示例

取自 Docusaurus 官网的真实示例:

sidebars.js
module.exports = {
  docs: [
    'introduction',
    {
      type: 'category',
      label: '入门',
      collapsed: false,
      items: ['installation', 'configuration', 'typescript-support'],
    },
    {
      type: 'category',
      label: '使用指南',
      items: [
        'guides/creating-pages',
        {
          文档功能: [
            'guideshttps://www.xnip.cn/doc/ZMAUaeSdintroduction',
            'guideshttps://www.xnip.cn/doc/JXxlBs7a',
            'guideshttps://www.xnip.cn/doc/InqRm4D1',
            'guideshttps://www.xnip.cn/doc/uMdITwUh',
            'guideshttps://www.xnip.cn/doc/dWeAfhhM',
            'guideshttps://www.xnip.cn/doc/ZMAUaeSdmulti-instance',
          ],
        },
        'blog',
        {
          type: 'category',
          label: '新增的 Markdown 功能',
          items: [
            'guides/markdown-features/introduction',
            'guides/markdown-features/react',
            'guides/markdown-features/tabs',
            'guides/markdown-features/code-blocks',
            'guides/markdown-features/admonitions',
            'guides/markdown-features/headings',
            'guides/markdown-features/inline-toc',
            'guides/markdown-features/assets',
            'guides/markdown-features/plugins',
          ],
        },
        'styling-layout',
        'static-assets',
        'search',
        'browser-support',
        'deployment',
        {
          type: 'category',
          label: '国际化',
          items: [
            {
              type: 'doc',
              id: 'i18n/introduction',
              label: '简介',
            },
            {
              type: 'doc',
              id: 'i18n/tutorial',
              label: '教程',
            },
            {
              type: 'doc',
              id: 'i18n/git',
              label: '使用 Git',
            },
            {
              type: 'doc',
              id: 'i18n/crowdin',
              label: '使用 Crowdin',
            },
          ],
        },
      ],
    },
    {
      type: 'category',
      label: '进阶指南',
      items: ['using-plugins', 'using-themes', 'presets'],
    },
    {
      type: 'category',
      label: '从 v1 迁移到 v2 版本',
      items: [
        'migration/migration-overview',
        'migration/migration-automated',
        'migration/migration-manual',
        'migration/migration-versioned-sites',
        'migration/migration-translated-sites',
      ],
    },
  ],
  api: [
    'cli',
    'docusaurus-core',
    'api/docusaurus.config.js',
    'lifecycle-apis',
    {
      type: 'category',
      label: '插件',
      items: [
        'api/plugins/plugins-overview',
        'api/plugins/plugin-content-docs',
        'api/plugins/plugin-content-blog',
        'api/plugins/plugin-content-pages',
        'api/plugins/plugin-client-redirects',
        'api/plugins/plugin-debug',
        'api/plugins/plugin-google-analytics',
        'api/plugins/plugin-google-gtag',
        'api/plugins/plugin-ideal-image',
        'api/plugins/plugin-pwa',
        'api/plugins/plugin-sitemap',
      ],
    },
    {
      type: 'category',
      label: '网站主题',
      items: [
        'api/themes/themes-overview',
        'api/themes/theme-configuration',
        'api/themes/theme-classic',
        'api/themes/theme-bootstrap',
        'api/themes/theme-live-codeblock',
        'api/themes/theme-search-algolia',
      ],
    },
  ],
};