自定义主题
Nextra 中的主题就像一个布局,它将被渲染为所有页面的包装器。本文档将引导您完成创建自定义主题的过程。
可选地,您可以部署一个示例并在遵循以下步骤的基础上进一步构建它
创建自定义主题
配置 Nextra 以使用主题
首先,您需要告诉 Nextra 使用您的自定义主题文件而不是官方主题文件。在您的 Next.js 配置中,您可以将主题文件的路径传递给 Nextra 插件
next.config.mjs
import nextra from 'nextra'
const withNextra = nextra({
theme: './theme.tsx'
})
// If you have other Next.js configurations, you can pass them as the parameter:
// export default withNextra({ /* other next.js config */ })
创建基本主题
您现在可以开始处理您的主题了!在您的根目录中,创建相应的 theme.tsx
文件,其中包含基本内容
theme.tsx
import type { NextraThemeLayoutProps } from 'nextra'
export default function Layout({ children }: NextraThemeLayoutProps) {
return (
<div>
<h1>My Theme</h1>
<div style={{ border: '1px solid' }}>{children}</div>
</div>
)
}
它接受一个 children
属性,该属性是当前页面的 MDX 内容,并在内容周围包装了一些其他元素。创建主题后,您可以简单地添加一个 MDX 文件作为 pages/index.mdx
并查看结果
在您的主题布局中,您可以使用 CSS 导入或其他方式对其进行样式设置。Next.js 钩子,例如 useRouter
、Head
也可用。
渲染活动页面的元数据
除了 children
之外,还会将一些其他有用的属性传递给主题布局。使用 pageOpts
属性,主题可以访问页面的元信息。
例如,让我们实现以下功能
- 在
<title>
中渲染页面标题 - 通过 MDX
<Wrapper>
组件显示简单的目录 - 通过前置 matter 添加
og:image
的元标记
theme.tsx
import Head from 'next/head'
import type { NextraThemeLayoutProps } from 'nextra'
import { MDXProvider } from 'nextra/mdx'
export default function Layout({ children, pageOpts }: NextraThemeLayoutProps) {
const { title, frontMatter } = pageOpts
return (
<>
<Head>
<title>{title}</title>
<meta name="og:image" content={frontMatter.image} />
</Head>
<MDXProvider components={{ wrapper: MyWrapper }}>{children}</MDXProvider>
</>
)
}
function MyWrapper({ children, toc }) {
return (
<>
<h1>My Theme</h1>
Table of Contents:
<ul>
{toc.map(heading => (
<li key={heading.value}>{heading.value}</li>
))}
</ul>
<div style={{ border: '1px solid' }}>{children}</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 ('route' in item && !('children' in item)) {
return (
<Link key={item.name} href={item.route}>
{item.route}
</Link>
)
}
})}
<div style={{ border: '1px solid' }}>{children}</div>
</div>
)
}
还有其他项目类型,例如 Folder
(用于目录)和 Meta
(用于 _meta.js
文件)。所有项目都已键入,因此您可以轻松了解属性。
高级用法
⚠️
高级用法的文档正在建设中。