MDX 和 React
Docusaurus 内置支持 MDX,它允许你在 Markdown 文件中编写 JSX 并将其渲染为 React 组件。
查看MDX文档,了解你可以用MDX做哪些酷炫的事情。
MDX格式非常严格,您可能会遇到编译错误。
使用MDX playground来调试它们,并确保您的语法是有效的。
Prettier,最流行的格式化工具,仅支持旧版的MDX v1。如果你得到了意外的格式化结果,你可能需要在问题区域前添加{/* prettier-ignore */},或者将*.mdx添加到你的.prettierignore中,直到Prettier对MDX v3有适当的支持。MDX的主要作者之一推荐使用remark-cli与remark-mdx。
导出组件
要在MDX文件中定义任何自定义组件,你必须导出它:只有以export开头的段落才会被解析为组件而不是普通文本。
export const Highlight = ({children, color}) => (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);
<Highlight color="#25c2a0">Docusaurus green</Highlight> and <Highlight color="#1877F2">Facebook blue</Highlight> are my favorite colors.
I can write **Markdown** alongside my _JSX_!
注意它如何渲染来自你的React组件的标记和Markdown语法:
我可以写Markdown和我的JSX一起!
由于所有文档文件都使用MDX解析,任何看起来像HTML的内容实际上都是JSX。因此,如果您需要内联样式组件,请遵循JSX风格并提供样式对象。
/* 不要这样做: */
<span style="background-color: red">Foospan>
/* 这样做: */
<span style={{backgroundColor: 'red'}}>Foospan>
导入组件
你也可以导入在其他文件中定义的自己的组件或通过npm安装的第三方组件。
<!-- Docusaurus theme component -->
import TOCInline from '@theme/TOCInline';
<!-- External component -->
import Button from '@mui/material/Button';
<!-- Custom component -->
import BrowserWindow from '@site/src/components/BrowserWindow';
虽然在Markdown中声明组件对于简单情况非常方便,但由于编辑器支持有限、解析错误的风险以及低可重用性,它变得难以维护。当您的组件涉及复杂的JS逻辑时,请使用单独的.js文件:
import React from 'react';
export default function Highlight({children, color}) {
return (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);
}
import Highlight from '@site/src/components/Highlight';
<Highlight color="#25c2a0">Docusaurus green</Highlight>
如果你在多个文件中使用相同的组件,你不需要在每个文件中都导入它——考虑将其添加到全局作用域中。参见下文
MDX 组件范围
除了导入组件和导出组件之外,在MDX中使用组件的第三种方法是将其注册到全局范围,这将使其在每个MDX文件中自动可用,无需任何导入语句。
例如,给定这个MDX文件:
- a
- list!
And some <Highlight>custom markup</Highlight>...
它将被编译成一个包含ul、li、p和Highlight元素的React组件。Highlight不是一个原生的HTML元素:你需要为它提供自己的React组件实现。
在Docusaurus中,MDX组件范围由@theme/MDXComponents文件提供。它本身不是一个React组件,与@theme/别名下的大多数其他导出不同:它是一个从标签名称(如Highlight)到它们的React组件实现的记录。
如果你swizzle这个组件,你会发现所有已经实现的标签,并且你可以通过swizzle相应的子组件来进一步自定义我们的实现,比如@theme/MDXComponents/Code(用于渲染Markdown代码块)。
如果你想注册额外的标签名称(如上面的标签),你应该考虑包装@theme/MDXComponents,这样你就不需要维护所有现有的映射。由于swizzle CLI目前还不允许包装非组件文件,你应该手动创建包装器:
import React from 'react';
// Import the original mapper
import MDXComponents from '@theme-original/MDXComponents';
import Highlight from '@site/src/components/Highlight';
export default {
// Re-use the default mapping
...MDXComponents,
// Map the "<Highlight>" tag to our Highlight component
// `Highlight` will receive all props that were passed to `<Highlight>` in MDX
Highlight,
};
现在,您可以在每个页面中自由使用,而无需编写导入语句:
I can conveniently use <Highlight color="#25c2a0">Docusaurus green</Highlight> everywhere!
我可以方便地在任何地方使用Docusaurus绿色!
我们故意使用大写标签名称,如Highlight。
从MDX v3+开始(Docusaurus v3+),小写标签名称总是被渲染为原生HTML元素,并且不会使用你提供的任何组件映射。
此功能由一个MDXProvider提供支持。如果您在React页面中导入Markdown,您必须通过MDXContent主题组件自行提供此提供者。
import React from 'react';
import FeatureDisplay from './_featureDisplay.mdx';
import MDXContent from '@theme/MDXContent';
export default function LandingPage() {
return (
<div>
<MDXContent>
<FeatureDisplay />
MDXContent>
div>
);
}
如果您不使用MDXContent包裹导入的MDX,全局作用域将不可用。
Markdown 和 JSX 互操作性
Docusaurus v3 正在使用 MDX v3。
MDX语法 大部分与 CommonMark 兼容,但由于你的 .mdx 文件可以使用 JSX 并且会被编译成真正的 React 组件,因此它更加严格(查看 playground)。
一些有效的CommonMark功能在MDX中无法使用(更多信息),特别是:
- 缩进代码块:使用三重反引号代替
- 自动链接 (
): 使用常规链接语法代替 ([http://localhost:3000](http://localhost:3000)) - HTML语法 (
): 使用JSX代替 () - 未转义的
{和<:使用\进行转义(\{和\<)
Docusaurus v3 使得可以通过以下选项选择支持不太严格的、标准的 CommonMark:
- 使用
mdx.format: md前置元数据 - 使用
.md文件扩展名并结合siteConfig.markdown.format: "detect"配置
此功能是 实验性的,目前存在一些 限制。
导入代码片段
你不仅可以导入包含组件定义的文件,还可以将任何代码文件作为原始文本导入,然后将其插入代码块中,这要归功于Webpack raw-loader。为了使用raw-loader,你首先需要在你的项目中安装它:
- npm
- Yarn
- pnpm
npm install --save raw-loader
yarn add raw-loader
pnpm add raw-loader
现在你可以从另一个文件中导入代码片段,如下所示:
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';
<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {useState} from 'react';
export default function MyComponent() {
const [bool, setBool] = useState(false);
return (
<div>
<p>MyComponent rendered !</p>
<p>bool={bool ? 'true' : 'false'}</p>
<p>
<button onClick={() => setBool((b) => !b)}>toggle bool</button>
</p>
</div>
);
}
查看在JSX中使用代码块以获取有关组件的更多详细信息。
你必须使用而不是Markdown的三重反引号```,因为后者会原样输出其内容,但你希望在这里插入导入的文本。
此功能是实验性的,未来可能会发生破坏性的API更改。
导入Markdown
你可以使用Markdown文件作为组件,并在其他地方导入它们,无论是在Markdown文件中还是在React页面中。每个MDX文件默认将其页面内容导出为React组件。在import语句中,你可以使用任何名称默认导入此组件,但必须遵循React的命名规则将其首字母大写。
按照惯例,使用_文件名前缀不会创建任何文档页面,并且意味着Markdown文件是一个"部分",将被其他文件导入。
<span>Hello {props.name}</span>
This is text some content from `_markdown-partial-example.mdx`.
import PartialExample from './_markdown-partial-example.mdx';
<PartialExample name="Sebastien" />
这是来自_markdown-partial-example.md的一些内容。
这样,您可以在多个页面之间重用内容,并避免重复材料。
可用导出
在MDX页面中,以下变量可作为全局变量使用:
frontMatter: 作为字符串键和值记录的前言部分;toc: 目录,作为标题的树形结构。另请参阅 Inline TOC 以获取更具体的用例。contentTitle: Markdown 标题,即 Markdown 文本中的第一个h1标题。如果没有(例如在 front matter 中指定了标题),则为undefined。
import TOCInline from '@theme/TOCInline';
import CodeBlock from '@theme/CodeBlock';
The table of contents for this page, serialized:
<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>
The front matter of this page:
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<p>The title of this page is: <b>{contentTitle}</b></p>
本页的目录,序列化:
[
{
"value": "导出组件",
"id": "exporting-components",
"level": 3
},
{
"value": "导入组件",
"id": "importing-components",
"level": 3
},
{
"value": "MDX 组件范围",
"id": "mdx-component-scope",
"level": 3
},
{
"value": "Markdown 和 JSX 互操作性",
"id": "markdown-and-jsx-interoperability",
"level": 3
},
{
"value": "导入代码片段",
"id": "importing-code-snippets",
"level": 2
},
{
"value": "导入 Markdown",
"id": "importing-markdown",
"level": 2
},
{
"value": "可用导出",
"id": "available-exports",
"level": 2
}
]
本页的前言:
- id: react
- description: 在 Docusaurus Markdown 文档中使用 React 的强大功能,感谢 MDX
- slug: /markdown-features/react
本页的标题是:MDX 和 React