Nextra 中文文档
自定义主题

自定义主题

在 Nextra 中,主题类似于布局,将作为所有页面的包装器进行渲染。本文档将指导您创建自定义主题的过程。

您可以选择部署一个示例,并按照以下步骤进一步构建它:

(opens in a new tab)

创建自定义主题

配置 Nextra 使用主题

首先,你需要告诉 Nextra 使用你的自定义主题文件,而不是官方的。 在你的 Next.js 配置中,你可以将主题文件的路径传递给 Nextra 插件:

next.config.js
const withNextra = require('nextra')({
  theme: './theme.tsx',
})
 
module.exports = withNextra({
  // 其他 Next.js 配置
  ...
})

创建基本主题

你现在可以开始着手开发你的主题了!在你的根目录下,创建相应的 theme.tsx 文件,内容如下:

theme.tsx
import type { NextraThemeLayoutProps } from 'nextra'
 
export default function Layout({ children }: NextraThemeLayoutProps) {
  return (
    <div>
      <h1>我的主题</h1>
      <div style={{ border: '1px solid' }}>{children}</div>
    </div>
  )
}

它接受一个 children 属性,这是当前页面的 MDX 内容,并在内容周围包裹一些其他元素。 创建主题后,你可以简单地添加一个 MDX 文件作为 pages/index.mdx,然后查看结果:

Custom theme

在你的主题布局中,你可以使用 CSS 导入或其他方式进行样式化。 Next.js 提供的钩子,比如 useRouterHead,也是可用的。

渲染活动页面的元数据

除了 children,一些其他有用的属性也传递给了主题布局。通过 pageOpts 属性,主题可以访问页面的元信息。

例如,让我们实现以下功能:

  • <title> 中渲染页面标题
  • 显示一个简单的目录
  • 通过前置元数据为 og:image 添加一个 meta 标签
theme.tsx
import Head from 'next/head'
import type { NextraThemeLayoutProps } from 'nextra'
 
export default function Layout({ children, pageOpts }: NextraThemeLayoutProps) {
  const { title, frontMatter, headings } = pageOpts
 
  return (
    <div>
      <Head>
        <title>{title}</title>
        <meta name="og:image" content={frontMatter.image} />
      </Head>
      <h1>My Theme</h1>
      Table of Contents:
      <ul>
        {headings.map(heading => (
          <li key={heading.value}>{heading.value}</li>
        ))}
      </ul>
      <div style={{ border: '1px solid' }}>{children}</div>
    </div>
  )
}

使用整个网站的页面映射

现在,如果你想要渲染类似侧边栏或导航栏这样的内容,它不仅依赖于当前页面的信息,还依赖于其他页面的信息,你可以使用 pageMap 值。

例如,我们可以渲染一个简单的导航列表,其中包含所有顶级页面:

theme.tsx
import Link from 'next/link'
import type { NextraThemeLayoutProps } from 'nextra'
 
export default function Layout({ children, pageOpts }: NextraThemeLayoutProps) {
  const { pageMap } = pageOpts
 
  return (
    <div>
      <h1>My Theme</h1>
      {pageMap.map(item => {
        if (item.kind === 'MdxPage') {
          return (
            <Link key={item.name} href={item.route}>
              {item.route}
            </Link>
          )
        }
        return null
      })}
      <div style={{ border: '1px solid' }}>{children}</div>
    </div>
  )
}

还有其他类型的项目,比如 Folder(用于目录)和 Meta(用于 _meta.json 文件)。 所有项目都有类型,因此您可以轻松了解其属性。

高级用法

⚠️

高级用法的文档正在建设中。