搅拌
在本节中,我们将介绍如何在 Docusaurus 中定制布局。
Déja vu...?
这一节类似于样式和布局,但这一次,我们将自定义 React 组件本身,而不是它们的样子。我们将讨论 Docusaurus 中的一个核心概念:swizzling,它允许更深层次的站点自定义。
在实践中,swizzling 允许用你自己的实现交换主题组件,它有两种模式:
为什么叫swizzling?
这个名字来源于 Objective-C 和 Swift-UI: method swizzling是改变现有选择器(方法)实现的过程。
对于 Docusaurus,组件混合意味着提供一个替代组件,该组件优先于主题提供的组件。
你可以把它想象成 React 组件的Monkey patch,使你能够覆盖默认实现。盖茨比有一个类似的概念,叫做主题阴影。
为了更深入地理解这 一点,您必须了解主题组件是如何解析的。
Swizzling 过程
概述
Docusaurus 提供了一个方便的交互式 CLI来混合组件。一般只需要记住以下命令:
- npm
- Yarn
- pnpm
npm run swizzle
yarn swizzle
pnpm run swizzle
它将在你的src/theme
目录下生成一个新组件,看起来应该像下面这个例子:
- Ejecting
- Wrapping
import React from "react";
export default function SomeComponent(props) {
// You can fully customize this implementation
// including changing the JSX, CSS and React hooks
return (
<div className="some-class">
<h1>Some Component</h1>
<p>Some component implementation details</p>
</div>
);
}
import React from "react";
import SomeComponent from "@theme-original/SomeComponent";
export default function SomeComponentWrapper(props) {
// You can enhance the original component,
// including adding extra props or JSX elements around it
return (
<>
<SomeComponent {...props} />
</>
);
}
要获得 swizzle 可用的所有主题和组件的概述,请运行:
- npm
- Yarn
- pnpm
npm run swizzle -- --list
yarn swizzle --list
pnpm run swizzle -- --list
使用--help
查看所有可用的 CLI 选项,或参考swizzle CLI 文档。
在搅拌组件后,重新启动开发服务器,以便 Docusaurus 了解新组件。
一定要了解哪些组件可以安全搅拌。有些组件是主题的内部实现细节。
docusaurus swizzle
只是一种自动的方法来帮助你搅拌组件。你也可以手动创建src/theme/SomeComponent.js
文件,Docusaurus 会解析。这个命令背后没有内在的魔法!
Ejecting
弹出主题组件是创建原始主题组件副本的过程,您可以对其进行完全的自定义和覆盖。
要弹出主题组件,可以交互式地使用 swizzle CLI,或者使用--eject
选项:
- npm
- Yarn
- pnpm
npm run swizzle [theme name] [component name] -- --eject
yarn swizzle [theme name] [component name] --eject
pnpm run swizzle [theme name] [component name] -- --eject
一个例子:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic Footer -- --eject
yarn swizzle @docusaurus/theme-classic Footer --eject
pnpm run swizzle @docusaurus/theme-classic Footer -- --eject
这将把当前<Footer />
组件的实现复制到你网站的src/theme
目录。Docusaurus 现在将使用这个<Footer />
组件副本而不是原始的。现在可以完全重新实现<Footer />
组件了。
import React from "react";
export default function Footer(props) {
return (
<footer>
<h1>This is my custom site footer</h1>
<p>And it is very different from the original</p>
</footer>
);
}
要在 Docusaurus 升级后保持被弹出的组件是最新的,请重新运行 eject
命令并将更改与git diff
进行比较。还建议在文件的顶部写一个简短的注释,解释所做的更改,以便在重新弹出后更容易地重新应用更改。
包装
包装主题组件是在原始主题组件周围创建包装器的过程,您可以对其进行增强。
要包装主题组件,可以交互式地使用 swizzle CLI,或者使用--wrap
选项:
- npm
- Yarn
- pnpm
npm run swizzle [theme name] [component name] -- --wrap
yarn swizzle [theme name] [component name] --wrap
pnpm run swizzle [theme name] [component name] -- --wrap
一个例子:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic Footer -- --wrap
yarn swizzle @docusaurus/theme-classic Footer --wrap
pnpm run swizzle @docusaurus/theme-classic Footer -- --wrap
这将在站点的src/theme
目录下创建一个包装器。Docusaurus 现在将使用<FooterWrapper>
组件而不是原来的组件。现在可以围绕原始组件添加自定义。
import React from "react";
import Footer from "@theme-original/Footer";
export default function FooterWrapper(props) {
return (
<>
<section>
<h2>Extra section</h2>
<p>This is an extra section that appears above the original footer</p>
</section>
<Footer {...props} />
</>
);
}
这个@theme-original
是什么?
Docusaurus 使用主题别名来解析要使用的主题组件。新创建的包装器使用@theme/SomeComponent
别名。@theme-original/SomeComponent
允许导入包装器隐藏的原始组件,而不会在包装器导入自身时创建无限导入循环。
包装主题是在现有主题周围添加额外组件的好方法,而无需弹出它 。 例如,你可以很容易地在每篇博客文章下添加一个自定义评论系统:
import React from "react";
import BlogPostItem from "@theme-original/BlogPostItem";
import MyCustomCommentSystem from "@site/src/MyCustomCommentSystem";
export default function BlogPostItemWrapper(props) {
return (
<>
<BlogPostItem {...props} />
<MyCustomCommentSystem />
</>
);
}
什么是安全的搅拌?
权力越大,责任越大
一些主题组件是主题的内部实现细节。Docusaurus 可以让你搅拌它们,但这可能有风险。
为什么有风险?
主题作者(包括我们)可能需要随时更新他们的主题:更改组件属性、名称、文件系统位置、类型……例如,考虑一个组件,它接收了两个属性name
和age
,但在重构之后,它现在接收了一个带有上述两个属性的person
属性。你的组件,仍然需要这两个属性,将渲染为undefined
。
此外,内部组件可能会消失。如果一个组件被命名为Sidebar
,后来它被重命名为DocSidebar
,那么你的 swizzzed 组件将被完全忽略。
标记为不安全的主题组件可能在主题次要版本之间以向后不兼容的方式更改。 升级主题(或 Docusaurus)时,您的自定义可能行为出乎意料,甚至可能破坏您的网站。
对于每个主题组件,swizzle CLI 将显示由主题作者声明的 3 个不同的安全级别:
- Safe: 这个组件是安全的,它的公共 API 被认为是稳定的,在主题主版本中不应该发生破坏性的变化
- Unsafe: 该组件是一个主题实现细节,不安全,并且可能在主题小版本中发生破坏性更改
- Forbidden: swizzle CLI 将阻止您对该组件进行搅拌,因为它根本不是 为搅拌而设计的
有些组件可以安全包装,但不能安全弹出。
不要太害怕使用不安全的组件:只要记住可能会发生破坏性的更改,并且您可能需要在小版本升级时手动升级您的自定义。
如果你有一个强大的用例搅拌一个不安全的组件,请在这里报告,我们将共同努力找到一个解决方案,使其安全。
我应该搅拌哪个组件?
为了达到预期的效果,您应该准确地搅拌哪个组件并不总是很清楚。@docusaurus/theme-classic
提供了大多数主题组件,大约有100 个组件!
打印所有@docusaurus/theme-classic
组件的概述:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic -- --list
yarn swizzle @docusaurus/theme-classic --list
pnpm run swizzle @docusaurus/theme-classic -- --list
您可以按照以下步骤找到要搅拌的适当组件:
- 组件描述. 有些组件提供简短的描述,这是找到正确组件的好方 法。
- 组件名称. 官方主题组件在语义上命名,因此您应该能够从名称推断其功能。swizzle CLI 允许您输入组件名称的一部分,以缩小可用选项的范围。例如,如果你运行
yarn swizzle @docusaurus/theme-classic
,然后输入Doc
,只会列出与 Doc 相关的组件。 - 从更高级的组件开始. 组件形成一个树,其中一些组件导入其他组件。每条路由都将与该路由将呈现的一个顶级组件相关联(它们中的大多数列在内容插件中的路由中)。例如,所有的博客文章页面都有
@theme/BlogPostPage
作为最上面的组件。您可以从混合这个组件开始,然后沿着组件树向下查找呈现您所要的内容的组件。不要忘记在找到正确的文件后通过删除文件来清除其余的文件,这样就不会维护太多的组件。 - 阅读主题源代码 并明智地使用搜索.
我需要搅拌吗?
Swizzling 最终意味着你必须维护一些与 Docusaurus 内部 api 交互的额外 React 代码。如果可以,在定制您的网站时考虑以下选择:
- 使用 CSS. CSS 规则和选择器通常可以帮助您实现相当程度的自定义。参考样式和布局了解更多细节。
- 使用翻译. 这可能听起来令人惊讶,但翻译最终只是自定义文本标签的一种方式。例如,如果你网站的默认语言是
en
,你仍然可以运行yarn write-translations -l en
并编辑发出的code.json
。请参阅i18n 教程了解更多细节。
用<Root>
包装你的站点
<Root>
组件呈现在 React 树的最顶层,在主题<Layout>
之上,并且永远不会卸载。
它是添加不应该跨导航(用户身份验证状态、购物车状态……)重新初始化的有状态逻辑的理想场所。
手动在src/theme/Root.js
创建一个文件:
import React from "react";
// Default implementation, that you can customize
export default function Root({ children }) {
return <>{children}</>;
}
使用这个组件来呈现 React 上下文提供程序。